aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6')
-rw-r--r--sources/shiboken6/.cmake.conf2
-rw-r--r--sources/shiboken6/ApiExtractor/CMakeLists.txt127
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaargument.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaargument.h13
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp1232
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.h33
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp33
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h164
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.cpp156
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.h30
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafield.cpp8
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafield.h7
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.cpp271
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.h89
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp544
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h113
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang_enums.h3
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h15
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h13
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetatype.cpp226
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetatype.h44
-rw-r--r--sources/shiboken6/ApiExtractor/addedfunction.cpp216
-rw-r--r--sources/shiboken6/ApiExtractor/addedfunction.h113
-rw-r--r--sources/shiboken6/ApiExtractor/addedfunction_p.h (renamed from sources/shiboken6/ApiExtractor/modifications_p.h)19
-rw-r--r--sources/shiboken6/ApiExtractor/anystringview_helpers.cpp56
-rw-r--r--sources/shiboken6/ApiExtractor/anystringview_helpers.h18
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.cpp436
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.h30
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractorresult.cpp60
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractorresult.h33
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h30
-rw-r--r--sources/shiboken6/ApiExtractor/arraytypeentry.h8
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp352
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h4
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp102
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h2
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangparser.h4
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp102
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangutils.h36
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp143
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/compilersupport.h9
-rw-r--r--sources/shiboken6/ApiExtractor/classdocumentation.cpp122
-rw-r--r--sources/shiboken6/ApiExtractor/classdocumentation.h15
-rw-r--r--sources/shiboken6/ApiExtractor/cmake_uninstall.cmake3
-rw-r--r--sources/shiboken6/ApiExtractor/codesnip.cpp6
-rw-r--r--sources/shiboken6/ApiExtractor/codesnip.h9
-rw-r--r--sources/shiboken6/ApiExtractor/complextypeentry.h36
-rw-r--r--sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/conditionalstreamreader.h2
-rw-r--r--sources/shiboken6/ApiExtractor/configurabletypeentry.h28
-rw-r--r--sources/shiboken6/ApiExtractor/constantvaluetypeentry.h2
-rw-r--r--sources/shiboken6/ApiExtractor/containertypeentry.h35
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion.cpp197
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion.h97
-rw-r--r--sources/shiboken6/ApiExtractor/customconversion_typedefs.h14
-rw-r--r--sources/shiboken6/ApiExtractor/customtypenentry.h2
-rw-r--r--sources/shiboken6/ApiExtractor/debughelpers_p.h56
-rw-r--r--sources/shiboken6/ApiExtractor/dependency.h4
-rw-r--r--sources/shiboken6/ApiExtractor/docparser.cpp144
-rw-r--r--sources/shiboken6/ApiExtractor/docparser.h28
-rw-r--r--sources/shiboken6/ApiExtractor/documentation.cpp6
-rw-r--r--sources/shiboken6/ApiExtractor/documentation.h14
-rw-r--r--sources/shiboken6/ApiExtractor/dotview.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/doxygenparser.cpp28
-rw-r--r--sources/shiboken6/ApiExtractor/doxygenparser.h2
-rw-r--r--sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp4
-rw-r--r--sources/shiboken6/ApiExtractor/enclosingclassmixin.h13
-rw-r--r--sources/shiboken6/ApiExtractor/enumtypeentry.h27
-rw-r--r--sources/shiboken6/ApiExtractor/enumvaluetypeentry.h4
-rw-r--r--sources/shiboken6/ApiExtractor/fileout.cpp48
-rw-r--r--sources/shiboken6/ApiExtractor/fileout.h2
-rw-r--r--sources/shiboken6/ApiExtractor/flagstypeentry.h7
-rw-r--r--sources/shiboken6/ApiExtractor/functiontypeentry.h6
-rw-r--r--sources/shiboken6/ApiExtractor/header_paths.h1
-rw-r--r--sources/shiboken6/ApiExtractor/icecc.cmake3
-rw-r--r--sources/shiboken6/ApiExtractor/include.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/include.h35
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp244
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h78
-rw-r--r--sources/shiboken6/ApiExtractor/modifications.cpp276
-rw-r--r--sources/shiboken6/ApiExtractor/modifications.h145
-rw-r--r--sources/shiboken6/ApiExtractor/modifications_typedefs.h25
-rw-r--r--sources/shiboken6/ApiExtractor/namespacetypeentry.h7
-rw-r--r--sources/shiboken6/ApiExtractor/objecttypeentry.h2
-rw-r--r--sources/shiboken6/ApiExtractor/optionsparser.cpp232
-rw-r--r--sources/shiboken6/ApiExtractor/optionsparser.h98
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp357
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h178
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel_enums.h15
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h31
-rw-r--r--sources/shiboken6/ApiExtractor/parser/enumvalue.cpp59
-rw-r--r--sources/shiboken6/ApiExtractor/parser/enumvalue.h20
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.cpp74
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.h26
-rw-r--r--sources/shiboken6/ApiExtractor/predefined_templates.cpp65
-rw-r--r--sources/shiboken6/ApiExtractor/predefined_templates.h4
-rw-r--r--sources/shiboken6/ApiExtractor/primitivetypeentry.h36
-rw-r--r--sources/shiboken6/ApiExtractor/propertyspec.cpp70
-rw-r--r--sources/shiboken6/ApiExtractor/propertyspec.h20
-rw-r--r--sources/shiboken6/ApiExtractor/pymethoddefentry.cpp13
-rw-r--r--sources/shiboken6/ApiExtractor/pymethoddefentry.h9
-rw-r--r--sources/shiboken6/ApiExtractor/pythontypeentry.h1
-rw-r--r--sources/shiboken6/ApiExtractor/qtcompat.h2
-rw-r--r--sources/shiboken6/ApiExtractor/qtdocparser.cpp197
-rw-r--r--sources/shiboken6/ApiExtractor/qtdocparser.h21
-rw-r--r--sources/shiboken6/ApiExtractor/reporthandler.cpp26
-rw-r--r--sources/shiboken6/ApiExtractor/smartpointertypeentry.h18
-rw-r--r--sources/shiboken6/ApiExtractor/templateargumententry.h2
-rw-r--r--sources/shiboken6/ApiExtractor/tests/CMakeLists.txt5
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp161
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp50
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp147
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp28
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp44
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testcontainer.cpp18
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp33
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp117
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp22
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp80
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp38
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testenum.cpp69
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp20
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp16
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp44
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp17
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp36
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h1
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp127
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp8
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testnamespace.cpp28
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp32
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp22
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp10
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp24
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp14
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testremovefield.cpp47
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testremovefield.h1
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp14
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp53
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp79
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testresolvetype.h1
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp23
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testtemplates.cpp120
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp18
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testutil.h8
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp10
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp25
-rw-r--r--sources/shiboken6/ApiExtractor/textstream.h36
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.cpp712
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.h108
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase_p.h8
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase_typedefs.h27
-rw-r--r--sources/shiboken6/ApiExtractor/typedefentry.h10
-rw-r--r--sources/shiboken6/ApiExtractor/typeparser.cpp22
-rw-r--r--sources/shiboken6/ApiExtractor/typeparser.h2
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp921
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.h82
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem_enums.h9
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem_typedefs.h82
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp1316
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser_p.h73
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemtypeentry.h18
-rw-r--r--sources/shiboken6/ApiExtractor/usingmember.h4
-rw-r--r--sources/shiboken6/ApiExtractor/valuetypeentry.h19
-rw-r--r--sources/shiboken6/ApiExtractor/xmlutils.cpp4
-rw-r--r--sources/shiboken6/ApiExtractor/xmlutils.h7
-rw-r--r--sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp21
-rw-r--r--sources/shiboken6/ApiExtractor/xmlutils_libxslt.h5
-rw-r--r--sources/shiboken6/ApiExtractor/xmlutils_qt.h5
-rw-r--r--sources/shiboken6/CMakeLists.txt12
-rw-r--r--sources/shiboken6/cmake/FindDocTools.cmake3
-rw-r--r--sources/shiboken6/cmake/ShibokenHelpers.cmake351
-rw-r--r--sources/shiboken6/cmake/ShibokenSetup.cmake34
-rw-r--r--sources/shiboken6/cmake_uninstall.cmake3
-rw-r--r--sources/shiboken6/config.tests/target_python_info/CMakeLists.txt5
-rw-r--r--sources/shiboken6/config.tests/target_qt_info/CMakeLists.txt5
-rw-r--r--sources/shiboken6/config.tests/target_qt_mkspec/CMakeLists.txt5
-rw-r--r--sources/shiboken6/data/CMakeLists.txt13
-rw-r--r--sources/shiboken6/data/Shiboken6Config-spec.cmake.in8
-rw-r--r--sources/shiboken6/data/Shiboken6ToolsConfig.cmake.in2
-rw-r--r--sources/shiboken6/data/shiboken6.pc.in8
-rw-r--r--sources/shiboken6/doc/CMakeLists.txt11
-rw-r--r--sources/shiboken6/doc/_static/css/qt_font.css8
-rw-r--r--sources/shiboken6/doc/_static/css/qt_style.css117
-rw-r--r--sources/shiboken6/doc/_static/shiboken.pngbin0 -> 17343 bytes
-rw-r--r--sources/shiboken6/doc/_static/shiboken.svg129
-rw-r--r--sources/shiboken6/doc/_themes/pysidedocs_qthelp/static/pyside.css8
-rw-r--r--sources/shiboken6/doc/conf.py.in72
-rw-r--r--sources/shiboken6/doc/considerations.rst70
-rw-r--r--sources/shiboken6/doc/examples/index.rst18
-rw-r--r--sources/shiboken6/doc/examples/samplebinding.rst246
-rw-r--r--sources/shiboken6/doc/gettingstarted.rst12
-rw-r--r--sources/shiboken6/doc/images/boostgen.pngbin153473 -> 0 bytes
-rw-r--r--sources/shiboken6/doc/images/converter.pngbin22467 -> 34204 bytes
-rw-r--r--sources/shiboken6/doc/images/converter.svg2522
-rw-r--r--sources/shiboken6/doc/images/genrunnerarch.pngbin68761 -> 0 bytes
-rw-r--r--sources/shiboken6/doc/images/genrunnerarch.svg654
-rw-r--r--sources/shiboken6/doc/images/qtforpython-underthehood.pngbin19144 -> 62001 bytes
-rw-r--r--sources/shiboken6/doc/images/qtforpython-underthehood.svg1502
-rw-r--r--sources/shiboken6/doc/images/shibokenqtarch.pngbin17602 -> 28655 bytes
-rw-r--r--sources/shiboken6/doc/images/shibokenqtarch.svg71
-rw-r--r--sources/shiboken6/doc/index.rst112
-rw-r--r--sources/shiboken6/doc/scripts/patch_qhp.py79
-rw-r--r--sources/shiboken6/doc/shiboken-genpyi.rst32
-rw-r--r--sources/shiboken6/doc/shibokengenerator.rst99
-rw-r--r--sources/shiboken6/doc/shibokenmodule.rst70
-rw-r--r--sources/shiboken6/doc/typediscovery.rst145
-rw-r--r--sources/shiboken6/doc/typesystem.rst1
-rw-r--r--sources/shiboken6/doc/typesystem_arguments.rst272
-rw-r--r--sources/shiboken6/doc/typesystem_builtin_types.rst14
-rw-r--r--sources/shiboken6/doc/typesystem_codeinjection.rst379
-rw-r--r--sources/shiboken6/doc/typesystem_containers.rst114
-rw-r--r--sources/shiboken6/doc/typesystem_conversionrule.rst184
-rw-r--r--sources/shiboken6/doc/typesystem_converters.rst285
-rw-r--r--sources/shiboken6/doc/typesystem_documentation.rst63
-rw-r--r--sources/shiboken6/doc/typesystem_manipulating_objects.rst687
-rw-r--r--sources/shiboken6/doc/typesystem_modify_function.rst68
-rw-r--r--sources/shiboken6/doc/typesystem_ownership.rst190
-rw-r--r--sources/shiboken6/doc/typesystem_solving_compilation.rst98
-rw-r--r--sources/shiboken6/doc/typesystem_specialfunctions.rst22
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst1208
-rw-r--r--sources/shiboken6/doc/typesystem_templates.rst145
-rw-r--r--sources/shiboken6/doc/typesystem_variables.rst180
-rw-r--r--sources/shiboken6/generator/CMakeLists.txt44
-rw-r--r--sources/shiboken6/generator/_config.py.in1
-rw-r--r--sources/shiboken6/generator/defaultvalue.cpp120
-rw-r--r--sources/shiboken6/generator/defaultvalue.h46
-rw-r--r--sources/shiboken6/generator/generator.cpp338
-rw-r--r--sources/shiboken6/generator/generator.h199
-rw-r--r--sources/shiboken6/generator/generatorcontext.cpp38
-rw-r--r--sources/shiboken6/generator/generatorcontext.h56
-rw-r--r--sources/shiboken6/generator/main.cpp792
-rw-r--r--sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp1217
-rw-r--r--sources/shiboken6/generator/qtdoc/qtdocgenerator.h91
-rw-r--r--sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp274
-rw-r--r--sources/shiboken6/generator/qtdoc/qtxmltosphinx.h28
-rw-r--r--sources/shiboken6/generator/qtdoc/rstformat.h22
-rw-r--r--sources/shiboken6/generator/shiboken/configurablescope.h33
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp4435
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h376
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_container.cpp164
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp486
-rw-r--r--sources/shiboken6/generator/shiboken/ctypenames.h40
-rw-r--r--sources/shiboken6/generator/shiboken/generatorargument.cpp110
-rw-r--r--sources/shiboken6/generator/shiboken/generatorargument.h60
-rw-r--r--sources/shiboken6/generator/shiboken/generatorstrings.h39
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp817
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.h54
-rw-r--r--sources/shiboken6/generator/shiboken/overloaddata.cpp134
-rw-r--r--sources/shiboken6/generator/shiboken/overloaddata.h7
-rw-r--r--sources/shiboken6/generator/shiboken/pytypenames.h27
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp1015
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h234
-rw-r--r--sources/shiboken6/generators/shiboken/shiboken.cpp7
-rw-r--r--sources/shiboken6/icecc.cmake3
-rw-r--r--sources/shiboken6/libshiboken/CMakeLists.txt71
-rw-r--r--sources/shiboken6/libshiboken/autodecref.h51
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp558
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.h116
-rw-r--r--sources/shiboken6/libshiboken/basewrapper_p.h135
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.cpp373
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.h28
-rw-r--r--sources/shiboken6/libshiboken/bufferprocs_py37.h4
-rw-r--r--sources/shiboken6/libshiboken/debugfreehook.cpp4
-rw-r--r--sources/shiboken6/libshiboken/embed/embedding_generator.py21
-rw-r--r--sources/shiboken6/libshiboken/embed/signature_bootstrap.py75
-rw-r--r--sources/shiboken6/libshiboken/helper.cpp248
-rw-r--r--sources/shiboken6/libshiboken/helper.h9
-rw-r--r--sources/shiboken6/libshiboken/pep384_issue33738.cpp121
-rw-r--r--sources/shiboken6/libshiboken/pep384ext.h89
-rw-r--r--sources/shiboken6/libshiboken/pep384impl.cpp373
-rw-r--r--sources/shiboken6/libshiboken/pep384impl.h109
-rw-r--r--sources/shiboken6/libshiboken/pep384impl_doc.rst704
-rw-r--r--sources/shiboken6/libshiboken/pyobjectholder.h86
-rw-r--r--sources/shiboken6/libshiboken/sbkarrayconverter.cpp6
-rw-r--r--sources/shiboken6/libshiboken/sbkarrayconverter.h6
-rw-r--r--sources/shiboken6/libshiboken/sbkarrayconverter_p.h2
-rw-r--r--sources/shiboken6/libshiboken/sbkcontainer.cpp7
-rw-r--r--sources/shiboken6/libshiboken/sbkcontainer.h81
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter.cpp145
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter.h14
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter_p.h15
-rw-r--r--sources/shiboken6/libshiboken/sbkcppstring.cpp5
-rw-r--r--sources/shiboken6/libshiboken/sbkcppstring.h2
-rw-r--r--sources/shiboken6/libshiboken/sbkcpptonumpy.cpp67
-rw-r--r--sources/shiboken6/libshiboken/sbkcpptonumpy.h41
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.cpp1113
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.h134
-rw-r--r--sources/shiboken6/libshiboken/sbkenum_p.h30
-rw-r--r--sources/shiboken6/libshiboken/sbkerrors.cpp72
-rw-r--r--sources/shiboken6/libshiboken/sbkerrors.h34
-rw-r--r--sources/shiboken6/libshiboken/sbkfeature_base.cpp408
-rw-r--r--sources/shiboken6/libshiboken/sbkfeature_base.h2
-rw-r--r--sources/shiboken6/libshiboken/sbkmodule.cpp462
-rw-r--r--sources/shiboken6/libshiboken/sbkmodule.h48
-rw-r--r--sources/shiboken6/libshiboken/sbknumpy.cpp24
-rw-r--r--sources/shiboken6/libshiboken/sbknumpyarrayconverter.cpp19
-rw-r--r--sources/shiboken6/libshiboken/sbknumpyview.cpp102
-rw-r--r--sources/shiboken6/libshiboken/sbknumpyview.h2
-rw-r--r--sources/shiboken6/libshiboken/sbkpython.h1
-rw-r--r--sources/shiboken6/libshiboken/sbksmartpointer.cpp58
-rw-r--r--sources/shiboken6/libshiboken/sbksmartpointer.h18
-rw-r--r--sources/shiboken6/libshiboken/sbkstaticstrings.cpp8
-rw-r--r--sources/shiboken6/libshiboken/sbkstaticstrings.h6
-rw-r--r--sources/shiboken6/libshiboken/sbkstring.cpp12
-rw-r--r--sources/shiboken6/libshiboken/sbkstring.h1
-rw-r--r--sources/shiboken6/libshiboken/sbktypefactory.cpp69
-rw-r--r--sources/shiboken6/libshiboken/sbkversion.h.in6
-rw-r--r--sources/shiboken6/libshiboken/sbkwindows.h17
-rw-r--r--sources/shiboken6/libshiboken/shiboken.h2
-rw-r--r--sources/shiboken6/libshiboken/signature.h4
-rw-r--r--sources/shiboken6/libshiboken/signature/signature.cpp90
-rw-r--r--sources/shiboken6/libshiboken/signature/signature_doc.rst376
-rw-r--r--sources/shiboken6/libshiboken/signature/signature_extend.cpp48
-rw-r--r--sources/shiboken6/libshiboken/signature/signature_globals.cpp163
-rw-r--r--sources/shiboken6/libshiboken/signature/signature_helper.cpp41
-rw-r--r--sources/shiboken6/libshiboken/signature_p.h11
-rw-r--r--sources/shiboken6/libshiboken/voidptr.cpp77
-rw-r--r--sources/shiboken6/shibokenmodule/CMakeLists.txt34
-rw-r--r--sources/shiboken6/shibokenmodule/Shiboken.pyi19
-rw-r--r--sources/shiboken6/shibokenmodule/__init__.py.in3
-rw-r--r--sources/shiboken6/shibokenmodule/_config.py.in1
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py1102
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py64
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py4
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject1
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py18
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py4
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py26
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py61
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py57
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py8
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py51
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py149
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py89
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json2
-rw-r--r--sources/shiboken6/shibokenmodule/shibokenmodule.cpp119
-rw-r--r--sources/shiboken6/shibokenmodule/typesystem_shiboken.xml126
-rw-r--r--sources/shiboken6/tests/CMakeLists.txt19
-rw-r--r--sources/shiboken6/tests/dumpcodemodel/CMakeLists.txt5
-rw-r--r--sources/shiboken6/tests/dumpcodemodel/main.cpp71
-rw-r--r--sources/shiboken6/tests/libminimal/CMakeLists.txt14
-rw-r--r--sources/shiboken6/tests/libminimal/containeruser.cpp55
-rw-r--r--sources/shiboken6/tests/libminimal/containeruser.h36
-rw-r--r--sources/shiboken6/tests/libminimal/libminimalmacros.h24
-rw-r--r--sources/shiboken6/tests/libminimal/listuser.cpp44
-rw-r--r--sources/shiboken6/tests/libminimal/listuser.h12
-rw-r--r--sources/shiboken6/tests/libminimal/minbool.h11
-rw-r--r--sources/shiboken6/tests/libminimal/obj.cpp5
-rw-r--r--sources/shiboken6/tests/libminimal/obj.h6
-rw-r--r--sources/shiboken6/tests/libminimal/spanuser.cpp58
-rw-r--r--sources/shiboken6/tests/libminimal/spanuser.h35
-rw-r--r--sources/shiboken6/tests/libminimal/val.h6
-rw-r--r--sources/shiboken6/tests/libother/CMakeLists.txt17
-rw-r--r--sources/shiboken6/tests/libother/extendsnoimplicitconversion.h3
-rw-r--r--sources/shiboken6/tests/libother/number.cpp20
-rw-r--r--sources/shiboken6/tests/libother/number.h4
-rw-r--r--sources/shiboken6/tests/libother/otherderived.cpp16
-rw-r--r--sources/shiboken6/tests/libother/otherderived.h16
-rw-r--r--sources/shiboken6/tests/libother/othermultiplederived.cpp11
-rw-r--r--sources/shiboken6/tests/libother/othermultiplederived.h6
-rw-r--r--sources/shiboken6/tests/libother/otherobjecttype.cpp5
-rw-r--r--sources/shiboken6/tests/libother/otherobjecttype.h8
-rw-r--r--sources/shiboken6/tests/libother/smartptrtester.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/CMakeLists.txt140
-rw-r--r--sources/shiboken6/tests/libsample/abstract.cpp71
-rw-r--r--sources/shiboken6/tests/libsample/abstract.h32
-rw-r--r--sources/shiboken6/tests/libsample/blackbox.cpp71
-rw-r--r--sources/shiboken6/tests/libsample/blackbox.h22
-rw-r--r--sources/shiboken6/tests/libsample/bucket.cpp26
-rw-r--r--sources/shiboken6/tests/libsample/bucket.h6
-rw-r--r--sources/shiboken6/tests/libsample/bytearray.cpp117
-rw-r--r--sources/shiboken6/tests/libsample/bytearray.h66
-rw-r--r--sources/shiboken6/tests/libsample/collector.cpp8
-rw-r--r--sources/shiboken6/tests/libsample/collector.h20
-rw-r--r--sources/shiboken6/tests/libsample/complex.cpp15
-rw-r--r--sources/shiboken6/tests/libsample/complex.h10
-rw-r--r--sources/shiboken6/tests/libsample/ctorconvrule.h6
-rw-r--r--sources/shiboken6/tests/libsample/cvlist.h6
-rw-r--r--sources/shiboken6/tests/libsample/derived.cpp50
-rw-r--r--sources/shiboken6/tests/libsample/derived.h22
-rw-r--r--sources/shiboken6/tests/libsample/echo.h50
-rw-r--r--sources/shiboken6/tests/libsample/exceptiontest.cpp7
-rw-r--r--sources/shiboken6/tests/libsample/exceptiontest.h2
-rw-r--r--sources/shiboken6/tests/libsample/expression.cpp83
-rw-r--r--sources/shiboken6/tests/libsample/expression.h29
-rw-r--r--sources/shiboken6/tests/libsample/filter.cpp22
-rw-r--r--sources/shiboken6/tests/libsample/filter.h28
-rw-r--r--sources/shiboken6/tests/libsample/functions.cpp121
-rw-r--r--sources/shiboken6/tests/libsample/functions.h27
-rw-r--r--sources/shiboken6/tests/libsample/handle.cpp8
-rw-r--r--sources/shiboken6/tests/libsample/handle.h32
-rw-r--r--sources/shiboken6/tests/libsample/implicitconv.cpp24
-rw-r--r--sources/shiboken6/tests/libsample/implicitconv.h26
-rw-r--r--sources/shiboken6/tests/libsample/injectcode.cpp33
-rw-r--r--sources/shiboken6/tests/libsample/injectcode.h26
-rw-r--r--sources/shiboken6/tests/libsample/list.h42
-rw-r--r--sources/shiboken6/tests/libsample/listuser.cpp37
-rw-r--r--sources/shiboken6/tests/libsample/listuser.h20
-rw-r--r--sources/shiboken6/tests/libsample/main.cpp220
-rw-r--r--sources/shiboken6/tests/libsample/mapuser.cpp42
-rw-r--r--sources/shiboken6/tests/libsample/mapuser.h21
-rw-r--r--sources/shiboken6/tests/libsample/modelindex.h29
-rw-r--r--sources/shiboken6/tests/libsample/modifications.cpp110
-rw-r--r--sources/shiboken6/tests/libsample/modifications.h62
-rw-r--r--sources/shiboken6/tests/libsample/modified_constructor.cpp3
-rw-r--r--sources/shiboken6/tests/libsample/modified_constructor.h4
-rw-r--r--sources/shiboken6/tests/libsample/multiple_derived.cpp33
-rw-r--r--sources/shiboken6/tests/libsample/multiple_derived.h134
-rw-r--r--sources/shiboken6/tests/libsample/noimplicitconversion.h9
-rw-r--r--sources/shiboken6/tests/libsample/nondefaultctor.h14
-rw-r--r--sources/shiboken6/tests/libsample/nontypetemplate.h4
-rw-r--r--sources/shiboken6/tests/libsample/null.h8
-rw-r--r--sources/shiboken6/tests/libsample/objectmodel.cpp15
-rw-r--r--sources/shiboken6/tests/libsample/objectmodel.h14
-rw-r--r--sources/shiboken6/tests/libsample/objecttype.cpp133
-rw-r--r--sources/shiboken6/tests/libsample/objecttype.h97
-rw-r--r--sources/shiboken6/tests/libsample/objecttypebyvalue.h20
-rw-r--r--sources/shiboken6/tests/libsample/objecttypeholder.cpp12
-rw-r--r--sources/shiboken6/tests/libsample/objecttypeholder.h12
-rw-r--r--sources/shiboken6/tests/libsample/objecttypelayout.cpp16
-rw-r--r--sources/shiboken6/tests/libsample/objecttypelayout.h13
-rw-r--r--sources/shiboken6/tests/libsample/objecttypeoperators.cpp12
-rw-r--r--sources/shiboken6/tests/libsample/objecttypeoperators.h22
-rw-r--r--sources/shiboken6/tests/libsample/objectview.cpp13
-rw-r--r--sources/shiboken6/tests/libsample/objectview.h16
-rw-r--r--sources/shiboken6/tests/libsample/oddbool.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/oddbool.h12
-rw-r--r--sources/shiboken6/tests/libsample/onlycopy.cpp30
-rw-r--r--sources/shiboken6/tests/libsample/onlycopy.h18
-rw-r--r--sources/shiboken6/tests/libsample/overload.cpp184
-rw-r--r--sources/shiboken6/tests/libsample/overload.h89
-rw-r--r--sources/shiboken6/tests/libsample/overloadsort.cpp35
-rw-r--r--sources/shiboken6/tests/libsample/overloadsort.h52
-rw-r--r--sources/shiboken6/tests/libsample/pairuser.cpp20
-rw-r--r--sources/shiboken6/tests/libsample/pairuser.h12
-rw-r--r--sources/shiboken6/tests/libsample/pen.cpp20
-rw-r--r--sources/shiboken6/tests/libsample/pen.h11
-rw-r--r--sources/shiboken6/tests/libsample/photon.cpp14
-rw-r--r--sources/shiboken6/tests/libsample/photon.h61
-rw-r--r--sources/shiboken6/tests/libsample/point.cpp79
-rw-r--r--sources/shiboken6/tests/libsample/point.h62
-rw-r--r--sources/shiboken6/tests/libsample/pointerholder.h13
-rw-r--r--sources/shiboken6/tests/libsample/pointf.cpp65
-rw-r--r--sources/shiboken6/tests/libsample/pointf.h52
-rw-r--r--sources/shiboken6/tests/libsample/polygon.cpp25
-rw-r--r--sources/shiboken6/tests/libsample/polygon.h16
-rw-r--r--sources/shiboken6/tests/libsample/privatector.h24
-rw-r--r--sources/shiboken6/tests/libsample/privatedtor.h19
-rw-r--r--sources/shiboken6/tests/libsample/protected.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/protected.h85
-rw-r--r--sources/shiboken6/tests/libsample/rect.h53
-rw-r--r--sources/shiboken6/tests/libsample/reference.cpp36
-rw-r--r--sources/shiboken6/tests/libsample/reference.h44
-rw-r--r--sources/shiboken6/tests/libsample/removednamespaces.h1
-rw-r--r--sources/shiboken6/tests/libsample/sample.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/sample.h4
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.cpp81
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.h51
-rw-r--r--sources/shiboken6/tests/libsample/sbkdate.h3
-rw-r--r--sources/shiboken6/tests/libsample/simplefile.cpp70
-rw-r--r--sources/shiboken6/tests/libsample/simplefile.h19
-rw-r--r--sources/shiboken6/tests/libsample/size.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/size.h67
-rw-r--r--sources/shiboken6/tests/libsample/sometime.cpp29
-rw-r--r--sources/shiboken6/tests/libsample/sometime.h27
-rw-r--r--sources/shiboken6/tests/libsample/stdcomplex.cpp32
-rw-r--r--sources/shiboken6/tests/libsample/stdcomplex.h55
-rw-r--r--sources/shiboken6/tests/libsample/str.cpp95
-rw-r--r--sources/shiboken6/tests/libsample/str.h33
-rw-r--r--sources/shiboken6/tests/libsample/strlist.cpp6
-rw-r--r--sources/shiboken6/tests/libsample/strlist.h33
-rw-r--r--sources/shiboken6/tests/libsample/templateptr.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/templateptr.h9
-rw-r--r--sources/shiboken6/tests/libsample/transform.cpp34
-rw-r--r--sources/shiboken6/tests/libsample/transform.h12
-rw-r--r--sources/shiboken6/tests/libsample/valueandvirtual.h13
-rw-r--r--sources/shiboken6/tests/libsample/virtualmethods.cpp14
-rw-r--r--sources/shiboken6/tests/libsample/virtualmethods.h42
-rw-r--r--sources/shiboken6/tests/libsample/voidholder.h17
-rw-r--r--sources/shiboken6/tests/libsmart/CMakeLists.txt17
-rw-r--r--sources/shiboken6/tests/libsmart/smart.cpp6
-rw-r--r--sources/shiboken6/tests/libsmart/smart.h1
-rw-r--r--sources/shiboken6/tests/libsmart/smart_integer.h8
-rw-r--r--sources/shiboken6/tests/libsmart/smart_obj.h4
-rw-r--r--sources/shiboken6/tests/libsmart/smart_sharedptr.h7
-rw-r--r--sources/shiboken6/tests/libsmart/smart_test.h13
-rw-r--r--sources/shiboken6/tests/libsmart/stduniqueptrtestbench.cpp16
-rw-r--r--sources/shiboken6/tests/libsmart/stduniqueptrtestbench.h4
-rw-r--r--sources/shiboken6/tests/minimalbinding/CMakeLists.txt23
-rw-r--r--sources/shiboken6/tests/minimalbinding/brace_pattern_test.py9
-rw-r--r--sources/shiboken6/tests/minimalbinding/containeruser_test.py44
-rw-r--r--sources/shiboken6/tests/minimalbinding/global.h2
-rw-r--r--sources/shiboken6/tests/minimalbinding/listuser_test.py24
-rw-r--r--sources/shiboken6/tests/minimalbinding/minbool_test.py22
-rw-r--r--sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in1
-rw-r--r--sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject10
-rw-r--r--sources/shiboken6/tests/minimalbinding/obj_test.py2
-rw-r--r--sources/shiboken6/tests/minimalbinding/spanuser_test.py42
-rw-r--r--sources/shiboken6/tests/minimalbinding/typedef_test.py52
-rw-r--r--sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml47
-rw-r--r--sources/shiboken6/tests/minimalbinding/val_test.py1
-rw-r--r--sources/shiboken6/tests/otherbinding/CMakeLists.txt21
-rw-r--r--sources/shiboken6/tests/otherbinding/collector_external_operator_test.py3
-rw-r--r--sources/shiboken6/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py28
-rw-r--r--sources/shiboken6/tests/otherbinding/extended_multiply_operator_test.py3
-rw-r--r--sources/shiboken6/tests/otherbinding/module_reload_test.py2
-rw-r--r--sources/shiboken6/tests/otherbinding/new_ctor_operator_test.py11
-rw-r--r--sources/shiboken6/tests/otherbinding/objtypehashes_test.py5
-rw-r--r--sources/shiboken6/tests/otherbinding/other-binding.txt.in2
-rw-r--r--sources/shiboken6/tests/otherbinding/otherbinding.pyproject17
-rw-r--r--sources/shiboken6/tests/otherbinding/otherderived_test.py15
-rw-r--r--sources/shiboken6/tests/otherbinding/othertypesystypedef_test.py3
-rw-r--r--sources/shiboken6/tests/otherbinding/signature_test.py5
-rw-r--r--sources/shiboken6/tests/otherbinding/smartptr_test.py2
-rw-r--r--sources/shiboken6/tests/otherbinding/star_import_test.py99
-rw-r--r--sources/shiboken6/tests/otherbinding/test_module_template.py13
-rw-r--r--sources/shiboken6/tests/otherbinding/typediscovery_test.py27
-rw-r--r--sources/shiboken6/tests/otherbinding/typesystem_other.xml4
-rw-r--r--sources/shiboken6/tests/otherbinding/usersprimitivefromothermodule_test.py2
-rw-r--r--sources/shiboken6/tests/otherbinding/wrongctor_test.py10
-rw-r--r--sources/shiboken6/tests/qtxmltosphinx/CMakeLists.txt5
-rw-r--r--sources/shiboken6/tests/qtxmltosphinx/main.cpp4
-rw-r--r--sources/shiboken6/tests/qtxmltosphinxtest/CMakeLists.txt5
-rw-r--r--sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.cpp107
-rw-r--r--sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.h2
-rw-r--r--sources/shiboken6/tests/samplebinding/CMakeLists.txt24
-rw-r--r--sources/shiboken6/tests/samplebinding/__del___test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/abstract_test.py11
-rw-r--r--sources/shiboken6/tests/samplebinding/addedfunction_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/addedfunction_with_container_args_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/argumentmodifications_test.py15
-rw-r--r--sources/shiboken6/tests/samplebinding/array_numpy_test.py10
-rw-r--r--sources/shiboken6/tests/samplebinding/array_sequence_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/bug_554_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/bug_704_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/bytearray_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/child_return_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/class_fields_test.py15
-rw-r--r--sources/shiboken6/tests/samplebinding/collector_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/complex_test.py11
-rw-r--r--sources/shiboken6/tests/samplebinding/conversion_operator_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/copy_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/ctorconvrule_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/cyclic_test.py7
-rw-r--r--sources/shiboken6/tests/samplebinding/date_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/decisor_test.py15
-rw-r--r--sources/shiboken6/tests/samplebinding/delete_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/deprecated_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/derived_test.py54
-rw-r--r--sources/shiboken6/tests/samplebinding/duck_punching_test.py13
-rw-r--r--sources/shiboken6/tests/samplebinding/echo_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/enum_test.py67
-rw-r--r--sources/shiboken6/tests/samplebinding/enumfromremovednamespace_test.py15
-rw-r--r--sources/shiboken6/tests/samplebinding/event_loop_call_virtual_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/event_loop_thread_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/exception_test.py28
-rw-r--r--sources/shiboken6/tests/samplebinding/filter_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/global.h1
-rw-r--r--sources/shiboken6/tests/samplebinding/handleholder_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/hashabletype_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/ignorederefop_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/implicitconv_numerical_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/implicitconv_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/inheritanceandscope_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/injectcode_test.py19
-rw-r--r--sources/shiboken6/tests/samplebinding/innerclass_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/intlist_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/intwrapper_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/invalid_virtual_return_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/keep_reference_test.py13
-rw-r--r--sources/shiboken6/tests/samplebinding/list_test.py7
-rw-r--r--sources/shiboken6/tests/samplebinding/lock_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/map_test.py15
-rw-r--r--sources/shiboken6/tests/samplebinding/metaclass_test.py14
-rw-r--r--sources/shiboken6/tests/samplebinding/mixed_mi_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/modelindex_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/modelview_test.py7
-rw-r--r--sources/shiboken6/tests/samplebinding/modifications_test.py40
-rw-r--r--sources/shiboken6/tests/samplebinding/modified_constructor_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/modifiedvirtualmethods_test.py12
-rw-r--r--sources/shiboken6/tests/samplebinding/multi_cpp_inheritance_test.py39
-rw-r--r--sources/shiboken6/tests/samplebinding/multiple_derived_test.py43
-rw-r--r--sources/shiboken6/tests/samplebinding/namespace_test.py55
-rw-r--r--sources/shiboken6/tests/samplebinding/newdivision_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/nondefaultctor_test.py9
-rw-r--r--sources/shiboken6/tests/samplebinding/nontypetemplate_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/nonzero_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/numericaltypedef_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/numpy_test.py5
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttype_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttype_with_named_args_test.py8
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttypebyvalue_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttypelayout_test.py28
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttypeoperators_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/oddbool_test.py14
-rw-r--r--sources/shiboken6/tests/samplebinding/onlycopyclass_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/overflow_test.py16
-rw-r--r--sources/shiboken6/tests/samplebinding/overload_sorting_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/overload_test.py12
-rw-r--r--sources/shiboken6/tests/samplebinding/overloadwithdefault_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_argument_invalidation_test.py9
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_delete_child_in_cpp_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_delete_child_in_python_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_delete_parent_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_invalidate_after_use_test.py12
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_invalidate_child_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_invalidate_parent_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_reparenting_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/ownership_transference_test.py16
-rw-r--r--sources/shiboken6/tests/samplebinding/pair_test.py13
-rw-r--r--sources/shiboken6/tests/samplebinding/pen_test.py1
-rw-r--r--sources/shiboken6/tests/samplebinding/point_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/pointerholder_test.py8
-rw-r--r--sources/shiboken6/tests/samplebinding/pointerprimitivetype_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/pointf_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/primitivereferenceargument_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/privatector_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/privatedtor_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/protected_test.py81
-rw-r--r--sources/shiboken6/tests/samplebinding/pstrlist_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/pystr_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/python_thread_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/receive_null_cstring_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/reference_test.py24
-rw-r--r--sources/shiboken6/tests/samplebinding/referencetopointer_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/renaming_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/return_null_test.py6
-rw-r--r--sources/shiboken6/tests/samplebinding/richcompare_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/sample-binding.txt.in1
-rw-r--r--sources/shiboken6/tests/samplebinding/sample_test.py48
-rw-r--r--sources/shiboken6/tests/samplebinding/samplebinding.pyproject131
-rw-r--r--sources/shiboken6/tests/samplebinding/samplesnippets.cpp36
-rw-r--r--sources/shiboken6/tests/samplebinding/simplefile_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/size_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/static_nonstatic_methods_test.py8
-rw-r--r--sources/shiboken6/tests/samplebinding/stdcomplex_test.py71
-rw-r--r--sources/shiboken6/tests/samplebinding/str_test.py38
-rw-r--r--sources/shiboken6/tests/samplebinding/strlist_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/templateinheritingclass_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/time_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/transform_test.py2
-rw-r--r--sources/shiboken6/tests/samplebinding/typeconverters_test.py20
-rw-r--r--sources/shiboken6/tests/samplebinding/typedealloc_test.py9
-rw-r--r--sources/shiboken6/tests/samplebinding/typedtordoublefree_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml114
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystypedef_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/unsafe_parent_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/useraddedctor_test.py7
-rw-r--r--sources/shiboken6/tests/samplebinding/virtualdtor_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/virtualmethods_test.py11
-rw-r--r--sources/shiboken6/tests/samplebinding/visibilitychange_test.py10
-rw-r--r--sources/shiboken6/tests/samplebinding/voidholder_test.py3
-rw-r--r--sources/shiboken6/tests/samplebinding/weakref_test.py4
-rw-r--r--sources/shiboken6/tests/samplebinding/writableclassdict_test.py6
-rw-r--r--sources/shiboken6/tests/shibokenmodule/module_test.py26
-rw-r--r--sources/shiboken6/tests/smartbinding/CMakeLists.txt23
-rw-r--r--sources/shiboken6/tests/smartbinding/smart-binding.txt.in1
-rw-r--r--sources/shiboken6/tests/smartbinding/smart_pointer_test.py5
-rw-r--r--sources/shiboken6/tests/smartbinding/smartbinding.pyproject7
-rw-r--r--sources/shiboken6/tests/smartbinding/std_optional_test.py1
-rw-r--r--sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py3
-rw-r--r--sources/shiboken6/tests/smartbinding/std_unique_ptr_test.py14
-rw-r--r--sources/shiboken6/tests/smartbinding/typesystem_smart.xml8
-rw-r--r--sources/shiboken6/tests/test_generator/CMakeLists.txt5
-rw-r--r--sources/shiboken6/tests/test_generator/run_test.cmake3
669 files changed, 30207 insertions, 21033 deletions
diff --git a/sources/shiboken6/.cmake.conf b/sources/shiboken6/.cmake.conf
index e9e426412..ecc0a433d 100644
--- a/sources/shiboken6/.cmake.conf
+++ b/sources/shiboken6/.cmake.conf
@@ -1,5 +1,5 @@
set(shiboken_MAJOR_VERSION "6")
-set(shiboken_MINOR_VERSION "4")
+set(shiboken_MINOR_VERSION "7")
set(shiboken_MICRO_VERSION "0")
set(shiboken_PRE_RELEASE_VERSION_TYPE "a")
set(shiboken_PRE_RELEASE_VERSION "1")
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt
index 2a779dad6..7aa2fbd11 100644
--- a/sources/shiboken6/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt
@@ -1,56 +1,88 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(apiextractor)
-cmake_minimum_required(VERSION 3.16)
-cmake_policy(VERSION 3.16)
+cmake_minimum_required(VERSION 3.18)
+cmake_policy(VERSION 3.18)
set(CMAKE_AUTOMOC ON)
set(apiextractor_SRC
-apiextractor.cpp
-apiextractorresult.cpp
-abstractmetaargument.cpp
-abstractmetabuilder.cpp
+abstractmetaargument.cpp abstractmetaargument.h
+abstractmetabuilder.cpp abstractmetabuilder.h abstractmetabuilder_p.h
abstractmetabuilder_helpers.cpp
-abstractmetaenum.cpp
-abstractmetafield.cpp
-abstractmetafunction.cpp
-abstractmetatype.cpp
-abstractmetalang.cpp
-classdocumentation.cpp
-codesnip.cpp
-codesniphelpers.cpp
-conditionalstreamreader.cpp
-documentation.cpp
-dotview.cpp
-enclosingclassmixin.cpp
-fileout.cpp
-messages.cpp
-modifications.cpp
-predefined_templates.cpp
-propertyspec.cpp
-pymethoddefentry.cpp
-reporthandler.cpp
-sourcelocation.cpp
-typeparser.cpp
-typesystem.cpp
-typesystemparser.cpp
-include.cpp
-typedatabase.cpp
-textstream.cpp
+abstractmetaenum.cpp abstractmetaenum.h
+abstractmetafield.cpp abstractmetafield.h
+abstractmetafunction.cpp abstractmetafunction.h
+abstractmetalang.cpp abstractmetalang.h abstractmetalang_helpers.h abstractmetalang_typedefs.h
+abstractmetatype.cpp abstractmetatype.h
+addedfunction.cpp addedfunction.h addedfunction_p.h
+anystringview_helpers.cpp anystringview_helpers.h
+apiextractor.cpp apiextractor.h apiextractorflags.h
+apiextractorresult.cpp apiextractorresult.h
+arraytypeentry.h
+classdocumentation.cpp classdocumentation.h
+codesnip.cpp codesnip.h
+codesniphelpers.cpp codesniphelpers.h
+complextypeentry.h
+conditionalstreamreader.cpp conditionalstreamreader.h
+configurabletypeentry.h
+constantvaluetypeentry.h
+containertypeentry.h
+customconversion.cpp customconversion.h customconversion_typedefs.h
+customtypenentry.h
+debughelpers_p.h
+dependency.h
+documentation.cpp documentation.h
+dotview.cpp dotview.h
+enclosingclassmixin.cpp enclosingclassmixin.h
+enumtypeentry.h
+enumvaluetypeentry.h
+exception.h
+fileout.cpp fileout.h
+flagstypeentry.h
+functiontypeentry.h
+graph.h
+header_paths.h
+include.cpp include.h
+messages.cpp messages.h
+modifications.cpp modifications.h modifications_typedefs.h
+namespacetypeentry.h
+objecttypeentry.h
+optionsparser.cpp optionsparser.h
+predefined_templates.cpp predefined_templates.h
+primitivetypeentry.h
+propertyspec.cpp propertyspec.h
+pymethoddefentry.cpp pymethoddefentry.h
+pythontypeentry.h
+reporthandler.cpp reporthandler.h
+smartpointertypeentry.h
+sourcelocation.cpp sourcelocation.h
+templateargumententry.h
+textstream.cpp textstream.h
+typedatabase.cpp typedatabase.h typedatabase_p.h typedatabase_typedefs.h
+typedefentry.h
+typeparser.cpp typeparser.h
+typesystem.cpp typesystem.h typesystem_enums.h typesystem_typedefs.h
+typesystemparser.cpp typesystemparser_p.h
+usingmember.h
+valuetypeentry.h
+varargstypeentry.h
+voidtypeentry.h
+xmlutils.cpp xmlutils.h xmlutils_libxslt.h xmlutils_qt.h
# Clang
-clangparser/compilersupport.cpp
-clangparser/clangparser.cpp
-clangparser/clangbuilder.cpp
-clangparser/clangdebugutils.cpp
-clangparser/clangutils.cpp
+clangparser/clangbuilder.cpp clangparser/clangbuilder.h
+clangparser/clangdebugutils.cpp clangparser/clangdebugutils.h
+clangparser/clangparser.cpp clangparser/clangparser.h
+clangparser/clangutils.cpp clangparser/clangutils.h
+clangparser/compilersupport.cpp clangparser/compilersupport.h
# Old parser
-parser/typeinfo.cpp
-parser/codemodel.cpp
-parser/enumvalue.cpp
-xmlutils.cpp
+parser/codemodel.cpp parser/codemodel.h parser/codemodel_fwd.h parser/codemodel_enums.h
+parser/enumvalue.cpp parser/enumvalue.h
+parser/typeinfo.cpp parser/typeinfo.h
)
-find_package(Qt${QT_MAJOR_VERSION}Xml 6.0)
find_package(LibXml2 2.6.32)
find_package(LibXslt 1.1.19)
@@ -73,7 +105,7 @@ target_include_directories(apiextractor PRIVATE ${CLANG_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/parser)
-target_link_libraries(apiextractor PUBLIC Qt${QT_MAJOR_VERSION}::Core)
+target_link_libraries(apiextractor PUBLIC Qt::Core)
target_link_libraries(apiextractor PRIVATE libclang)
if (HAS_LIBXSLT)
@@ -86,9 +118,10 @@ if (HAS_LIBXSLT)
endif()
if (NOT DISABLE_DOCSTRINGS)
- target_sources(apiextractor PRIVATE docparser.cpp
- doxygenparser.cpp
- qtdocparser.cpp)
+ target_sources(apiextractor PRIVATE
+ docparser.cpp docparser.h
+ doxygenparser.cpp doxygenparser.h
+ qtdocparser.cpp qtdocparser.h)
endif()
target_compile_definitions(apiextractor
@@ -98,7 +131,7 @@ target_compile_definitions(apiextractor
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
if (BUILD_TESTS)
- find_package(Qt${QT_MAJOR_VERSION}Test 6.0 REQUIRED)
+ find_package(Qt6 REQUIRED COMPONENTS Test)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests)
enable_testing()
add_subdirectory(tests)
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
index a34cfde9f..05cebe10a 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abstractmetaargument.h"
+#include "abstractmetatype.h"
#include "documentation.h"
#include "qtcompat.h"
@@ -37,9 +38,9 @@ AbstractMetaArgument::AbstractMetaArgument(const AbstractMetaArgument &) = defau
AbstractMetaArgument &AbstractMetaArgument::operator=(const AbstractMetaArgument &) = default;
-AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) = default;
+AbstractMetaArgument::AbstractMetaArgument(AbstractMetaArgument &&) noexcept = default;
-AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) = default;
+AbstractMetaArgument &AbstractMetaArgument::operator=(AbstractMetaArgument &&) noexcept = default;
const AbstractMetaType &AbstractMetaArgument::type() const
{
@@ -57,6 +58,11 @@ const AbstractMetaType &AbstractMetaArgument::modifiedType() const
return d->m_modifiedType;
}
+bool AbstractMetaArgument::isTypeModified() const
+{
+ return modifiedType() != type();
+}
+
bool AbstractMetaArgument::isModifiedRemoved() const
{
return d->m_modifiedRemoved;
@@ -185,7 +191,7 @@ QDebug operator<<(QDebug d, const AbstractMetaArgument *aa)
d.noquote();
d.nospace();
d << "AbstractMetaArgument(";
- if (aa)
+ if (aa != nullptr)
d << aa->toString();
else
d << '0';
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.h b/sources/shiboken6/ApiExtractor/abstractmetaargument.h
index ef68b8687..38402e369 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaargument.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.h
@@ -4,15 +4,11 @@
#ifndef ABSTRACTMETAARGUMENT_H
#define ABSTRACTMETAARGUMENT_H
-#include "abstractmetalang_typedefs.h"
-#include "abstractmetatype.h"
-#include "typesystem_enums.h"
-#include "typesystem_typedefs.h"
-
#include <QtCore/QSharedDataPointer>
QT_FORWARD_DECLARE_CLASS(QDebug)
+class AbstractMetaType;
class AbstractMetaArgumentData;
class Documentation;
@@ -23,15 +19,14 @@ public:
~AbstractMetaArgument();
AbstractMetaArgument(const AbstractMetaArgument &);
AbstractMetaArgument &operator=(const AbstractMetaArgument &);
- AbstractMetaArgument(AbstractMetaArgument &&);
- AbstractMetaArgument &operator=(AbstractMetaArgument &&);
-
+ AbstractMetaArgument(AbstractMetaArgument &&) noexcept;
+ AbstractMetaArgument &operator=(AbstractMetaArgument &&) noexcept;
const AbstractMetaType &type() const;
void setType(const AbstractMetaType &type);
void setModifiedType(const AbstractMetaType &type);
const AbstractMetaType &modifiedType() const;
- bool isTypeModified() const { return modifiedType() != type(); }
+ bool isTypeModified() const;
bool isModifiedRemoved() const;
void setModifiedRemoved(bool v);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 1391a7b0a..29566a272 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -2,10 +2,14 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abstractmetabuilder_p.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
#include "abstractmetafield.h"
#include "abstractmetafunction.h"
+#include "abstractmetatype.h"
+#include "addedfunction.h"
#include "graph.h"
+#include "debughelpers_p.h"
#include "exception.h"
#include "messages.h"
#include "propertyspec.h"
@@ -39,6 +43,7 @@
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
+#include <QtCore/QMetaObject>
#include <QtCore/QQueue>
#include <QtCore/QRegularExpression>
#include <QtCore/QTemporaryFile>
@@ -50,11 +55,9 @@
using namespace Qt::StringLiterals;
-static inline QString colonColon() { return QStringLiteral("::"); }
-
static QString stripTemplateArgs(const QString &name)
{
- int pos = name.indexOf(u'<');
+ const auto pos = name.indexOf(u'<');
return pos < 0 ? name : name.left(pos);
}
@@ -64,6 +67,31 @@ static void fixArgumentIndexes(AbstractMetaArgumentList *list)
(*list)[i].setArgumentIndex(i);
}
+bool operator<(const RejectEntry &re1, const RejectEntry &re2)
+{
+ return re1.reason != re2.reason
+ ? (re1.reason < re2.reason) : (re1.sortkey < re2.sortkey);
+}
+
+QTextStream &operator<<(QTextStream &str, const RejectEntry &re)
+{
+ str << re.signature;
+ if (!re.message.isEmpty())
+ str << ": " << re.message;
+ return str;
+}
+
+static void applyCachedFunctionModifications(AbstractMetaFunction *metaFunction,
+ const FunctionModificationList &functionMods)
+{
+ for (const FunctionModification &mod : functionMods) {
+ if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
+ metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
+ if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
+ metaFunction->setAllowThreadModification(mod.allowThread());
+ }
+}
+
bool AbstractMetaBuilderPrivate::m_useGlobalHeader = false;
bool AbstractMetaBuilderPrivate::m_codeModelTestMode = false;
@@ -72,13 +100,6 @@ AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() :
{
}
-AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate()
-{
- qDeleteAll(m_templates);
- qDeleteAll(m_smartPointers);
- qDeleteAll(m_metaClasses);
-}
-
AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate)
{
d->q = this;
@@ -135,36 +156,41 @@ const AbstractMetaEnumList &AbstractMetaBuilder::globalEnums() const
return d->m_globalEnums;
}
-const QHash<const TypeEntry *, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const
+const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const
{
return d->m_enums;
}
-void AbstractMetaBuilderPrivate::checkFunctionModifications()
+const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() const
+{
+ return d->m_typedefTargetToName;
+}
+
+void AbstractMetaBuilderPrivate::checkFunctionModifications() const
{
const auto &entries = TypeDatabase::instance()->entries();
for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
- const TypeEntry *entry = it.value();
+ TypeEntryCPtr entry = it.value();
if (!entry)
continue;
if (!entry->isComplex() || !entry->generateCode())
continue;
- auto centry = static_cast<const ComplexTypeEntry *>(entry);
+ auto centry = std::static_pointer_cast<const ComplexTypeEntry>(entry);
if (!centry->generateCode())
continue;
FunctionModificationList modifications = centry->functionModifications();
- for (const FunctionModification &modification : qAsConst(modifications)) {
+ for (const FunctionModification &modification : std::as_const(modifications)) {
QString signature = modification.signature();
QString name = signature.trimmed();
name.truncate(name.indexOf(u'('));
- AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry);
+ const auto clazz = AbstractMetaClass::findClass(m_metaClasses, centry);
if (!clazz)
continue;
@@ -172,13 +198,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
QStringList possibleSignatures;
for (const auto &function : clazz->functions()) {
if (function->implementingClass() == clazz
- && modification.matches(function->minimalSignature())) {
+ && modification.matches(function->modificationSignatures())) {
found = true;
break;
}
if (function->originalName() == name) {
- possibleSignatures.append(function->minimalSignature() + u" in "_s
+ const QString signatures = function->modificationSignatures().join(u'/');
+ possibleSignatures.append(signatures + u" in "_s
+ function->implementingClass()->name());
}
}
@@ -193,14 +220,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument,
- const AbstractMetaClass *currentClass)
+AbstractMetaClassPtr AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument,
+ const AbstractMetaClassCPtr &currentClass)
{
- AbstractMetaClass *returned = nullptr;
+ AbstractMetaClassPtr returned;
auto type = translateType(argument->type(), currentClass);
if (!type.has_value())
return returned;
- const TypeEntry *entry = type->typeEntry();
+ TypeEntryCPtr entry = type->typeEntry();
if (entry && entry->isComplex())
returned = AbstractMetaClass::findClass(m_metaClasses, entry);
return returned;
@@ -210,20 +237,20 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentMod
* Checks the argument of a hash function and flags the type if it is a complex type
*/
void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
if (function_item->isDeleted())
return;
ArgumentList arguments = function_item->arguments();
if (arguments.size() >= 1) { // (Class, Hash seed).
- if (AbstractMetaClass *cls = argumentToClass(arguments.at(0), currentClass))
+ if (AbstractMetaClassPtr cls = argumentToClass(arguments.at(0), currentClass))
cls->setHashFunction(function_item->name());
}
}
void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceModelItem &nsItem)
{
- const FunctionList &streamOps = nsItem->findFunctions(u"operator<<"_s);
+ const FunctionList &streamOps = nsItem->findFunctions("operator<<");
for (const FunctionModelItem &item : streamOps)
registerToStringCapability(item, nullptr);
for (const NamespaceModelItem &ni : nsItem->namespaces())
@@ -235,13 +262,13 @@ void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceMod
*/
void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 2) {
if (arguments.at(0)->type().toString() == u"QDebug") {
const ArgumentModelItem &arg = arguments.at(1);
- if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) {
+ if (AbstractMetaClassPtr cls = argumentToClass(arg, currentClass)) {
if (arg->type().indirections() < 2)
cls->setToStringCapability(true, int(arg->type().indirections()));
}
@@ -250,7 +277,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI
}
void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
if (item->accessPolicy() != Access::Public)
return;
@@ -269,8 +296,8 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
firstArgumentIsSelf = false;
} else {
auto type = translateType(item->type(), currentClass);
- const TypeEntry *retType = type.has_value() ? type->typeEntry() : nullptr;
- AbstractMetaClass *otherArgClass = argumentToClass(itemArguments.at(1), currentClass);
+ const auto retType = type.has_value() ? type->typeEntry() : TypeEntryCPtr{};
+ const auto otherArgClass = argumentToClass(itemArguments.at(1), currentClass);
if (otherArgClass && retType
&& (retType->isValue() || retType->isObject())
&& retType != baseoperandClass->typeEntry()
@@ -279,11 +306,14 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
firstArgumentIsSelf = false;
}
}
- if (baseoperandClass == nullptr)
+ if (!baseoperandClass) {
+ rejectFunction(item, currentClass, AbstractMetaBuilder::UnmatchedOperator,
+ u"base operand class not found."_s);
return;
+ }
if (item->isSpaceshipOperator() && !item->isDeleted()) {
- baseoperandClass->addSynthesizedComparisonOperators();
+ AbstractMetaClass::addSynthesizedComparisonOperators(baseoperandClass);
return;
}
@@ -320,12 +350,16 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
}
metaFunction->setFlags(flags);
metaFunction->setAccess(Access::Public);
- baseoperandClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(baseoperandClass, AbstractMetaFunctionCPtr(metaFunction));
+ if (!metaFunction->arguments().isEmpty()) {
+ const auto include = metaFunction->arguments().constFirst().type().typeEntry()->include();
+ baseoperandClass->typeEntry()->addArgumentInclude(include);
+ }
Q_ASSERT(!metaFunction->wasPrivate());
}
bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
ArgumentList itemArguments = item->arguments();
if (itemArguments.size() != 2 || item->accessPolicy() != Access::Public)
@@ -352,10 +386,9 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
streamFunction->setArguments(arguments);
- *streamFunction += AbstractMetaFunction::FinalInTargetLang;
streamFunction->setAccess(Access::Public);
- AbstractMetaClass *funcClass;
+ AbstractMetaClassPtr funcClass;
if (!streamClass->typeEntry()->generateCode()) {
AbstractMetaArgumentList reverseArgs = streamFunction->arguments();
@@ -368,8 +401,8 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
funcClass = streamClass;
}
- funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction));
- auto *funcTe = funcClass->typeEntry();
+ AbstractMetaClass::addFunction(funcClass, AbstractMetaFunctionCPtr(streamFunction));
+ auto funcTe = funcClass->typeEntry();
if (funcClass == streamClass)
funcTe->addArgumentInclude(streamedClass->typeEntry()->include());
else
@@ -380,7 +413,7 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
static bool metaEnumLessThan(const AbstractMetaEnum &e1, const AbstractMetaEnum &e2)
{ return e1.fullName() < e2.fullName(); }
-static bool metaClassLessThan(const AbstractMetaClass *c1, const AbstractMetaClass *c2)
+static bool metaClassLessThan(const AbstractMetaClassCPtr &c1, const AbstractMetaClassCPtr &c2)
{ return c1->fullName() < c2->fullName(); }
static bool metaFunctionLessThan(const AbstractMetaFunctionCPtr &f1, const AbstractMetaFunctionCPtr &f2)
@@ -393,8 +426,8 @@ void AbstractMetaBuilderPrivate::sortLists()
// this is a temporary solution before new type revision implementation
// We need move QMetaObject register before QObject.
Dependencies additionalDependencies;
- if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QObject")) {
- if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QMetaObject")) {
+ if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QObject")) {
+ if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QMetaObject")) {
Dependency dependency;
dependency.parent = qMetaObjectClass;
dependency.child = qObjectClass;
@@ -403,7 +436,7 @@ void AbstractMetaBuilderPrivate::sortLists()
}
m_metaClasses = classesTopologicalSorted(m_metaClasses, additionalDependencies);
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses))
+ for (const auto &cls : std::as_const(m_metaClasses))
cls->sortFunctions();
// Ensure that indexes are in alphabetical order, roughly, except
@@ -420,7 +453,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
unsigned clangFlags)
{
clang::Builder builder;
- builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes());
+ builder.setForceProcessSystemIncludes(TypeDatabase::instance()->forceProcessSystemIncludes());
if (addCompilerSupportArguments) {
if (level == LanguageLevel::Default)
level = clang::emulatedCompilerLanguageLevel();
@@ -431,12 +464,12 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
clangFlags, builder)
? builder.dom() : FileModelItem();
const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics();
- if (const int diagnosticsCount = diagnostics.size()) {
+ if (const auto diagnosticsCount = diagnostics.size()) {
QDebug d = qWarning();
d.nospace();
d.noquote();
d << "Clang: " << diagnosticsCount << " diagnostic messages:\n";
- for (int i = 0; i < diagnosticsCount; ++i)
+ for (qsizetype i = 0; i < diagnosticsCount; ++i)
d << " " << diagnostics.at(i) << '\n';
}
return result;
@@ -447,7 +480,7 @@ static QStringList functionCandidates(const AbstractMetaFunctionCList &list,
const QString &signature)
{
QString name = signature;
- const int parenPos = name.indexOf(u'(');
+ const auto parenPos = name.indexOf(u'(');
if (parenPos > 0)
name.truncate(parenPos);
QStringList result;
@@ -468,18 +501,18 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
// Start the generation...
const ClassList &typeValues = dom->classes();
- ReportHandler::startProgress("Generating class model ("
- + QByteArray::number(typeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated class model ("
+ + QByteArray::number(typeValues.size()) + ").");
for (const ClassModelItem &item : typeValues) {
- if (AbstractMetaClass *cls = traverseClass(dom, item, nullptr))
- addAbstractMetaClass(cls, item.data());
+ if (const auto cls = traverseClass(dom, item, nullptr))
+ addAbstractMetaClass(cls, item.get());
}
// We need to know all global enums
const EnumList &enums = dom->enums();
- ReportHandler::startProgress("Generating enum model ("
- + QByteArray::number(enums.size()) + ")...");
+ ReportHandler::startProgress("Generated enum model ("
+ + QByteArray::number(enums.size()) + ").");
for (const EnumModelItem &item : enums) {
auto metaEnum = traverseEnum(item, nullptr, QSet<QString>());
if (metaEnum.has_value()) {
@@ -489,19 +522,19 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
const auto &namespaceTypeValues = dom->namespaces();
- ReportHandler::startProgress("Generating namespace model ("
- + QByteArray::number(namespaceTypeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated namespace model ("
+ + QByteArray::number(namespaceTypeValues.size()) + ").");
for (const NamespaceModelItem &item : namespaceTypeValues)
traverseNamespace(dom, item);
// Go through all typedefs to see if we have defined any
// specific typedefs to be used as classes.
const TypeDefList typeDefs = dom->typeDefs();
- ReportHandler::startProgress("Resolving typedefs ("
- + QByteArray::number(typeDefs.size()) + ")...");
+ ReportHandler::startProgress("Resolved typedefs ("
+ + QByteArray::number(typeDefs.size()) + ").");
for (const TypeDefModelItem &typeDef : typeDefs) {
- if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, nullptr))
- addAbstractMetaClass(cls, typeDef.data());
+ if (const auto cls = traverseTypeDef(dom, typeDef, nullptr))
+ addAbstractMetaClass(cls, typeDef.get());
}
traverseTypesystemTypedefs();
@@ -518,7 +551,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
if (func->accessPolicy() != Access::Public || func->name().startsWith(u"operator"))
continue;
- FunctionTypeEntry *funcEntry = types->findFunctionType(func->name());
+ FunctionTypeEntryPtr funcEntry = types->findFunctionType(func->name());
if (!funcEntry || !funcEntry->generateCode())
continue;
@@ -539,8 +572,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
m_globalFunctions << metaFuncPtr;
}
- ReportHandler::startProgress("Fixing class inheritance...");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ ReportHandler::startProgress("Fixed class inheritance.");
+ for (const auto &cls : std::as_const(m_metaClasses)) {
if (cls->needsInheritanceSetup()) {
setupInheritance(cls);
traverseUsingMembers(cls);
@@ -552,14 +585,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
}
- ReportHandler::startProgress("Detecting inconsistencies in class model...");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
- cls->fixFunctions();
+ ReportHandler::startProgress("Checked for inconsistencies in class model.");
+ for (const auto &cls : std::as_const(m_metaClasses)) {
+ AbstractMetaClass::fixFunctions(cls);
if (cls->canAddDefaultConstructor())
- cls->addDefaultConstructor();
+ AbstractMetaClass::addDefaultConstructor(cls);
if (cls->canAddDefaultCopyConstructor())
- cls->addDefaultCopyConstructor();
+ AbstractMetaClass::addDefaultCopyConstructor(cls);
const bool avoidProtectedHack = flags.testFlag(ApiExtractorFlag::AvoidProtectedHack);
const bool vco =
@@ -570,10 +603,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
const auto &allEntries = types->entries();
- ReportHandler::startProgress("Detecting inconsistencies in typesystem ("
- + QByteArray::number(allEntries.size()) + ")...");
+ ReportHandler::startProgress("Checked for inconsistencies in typesystem ("
+ + QByteArray::number(allEntries.size()) + ").");
for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
- TypeEntry *entry = it.value();
+ const TypeEntryPtr &entry = it.value();
if (!entry->isPrimitive()) {
if ((entry->isValue() || entry->isObject())
&& !types->shouldDropTypeEntry(entry->qualifiedCppName())
@@ -583,11 +616,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
&& !AbstractMetaClass::findClass(m_metaClasses, entry)) {
qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry)));
} else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
- auto fte = static_cast<const FunctionTypeEntry *>(entry);
+ auto fte = std::static_pointer_cast<const FunctionTypeEntry>(entry);
const QStringList &signatures = fte->signatures();
for (const QString &signature : signatures) {
bool ok = false;
- for (const auto &func : qAsConst(m_globalFunctions)) {
+ for (const auto &func : std::as_const(m_globalFunctions)) {
if (signature == func->minimalSignature()) {
ok = true;
break;
@@ -601,9 +634,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
}
} else if (entry->isEnum() && entry->generateCode()) {
- auto enumEntry = static_cast<const EnumTypeEntry *>(entry);
- AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses,
- enumEntry->parent());
+ const auto enumEntry = std::static_pointer_cast<const EnumTypeEntry>(entry);
+ const auto cls = AbstractMetaClass::findClass(m_metaClasses,
+ enumEntry->parent());
const bool enumFound = cls
? cls->findEnum(entry->targetLangEntryName()).has_value()
@@ -620,7 +653,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
{
- const FunctionList &hashFunctions = dom->findFunctions(u"qHash"_s);
+ const FunctionList &hashFunctions = dom->findFunctions("qHash");
for (const FunctionModelItem &item : hashFunctions)
registerHashFunction(item, nullptr);
}
@@ -643,13 +676,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
}
- ReportHandler::startProgress("Checking inconsistencies in function modifications...");
+ ReportHandler::startProgress("Checked for inconsistencies in function modifications.");
checkFunctionModifications();
- ReportHandler::startProgress("Writing log files...");
+ ReportHandler::startProgress("Wrote log files.");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ for (const auto &cls : std::as_const(m_metaClasses)) {
// setupEquals(cls);
// setupComparable(cls);
setupExternalConversion(cls);
@@ -693,10 +726,10 @@ bool AbstractMetaBuilder::build(const QByteArrayList &arguments,
{
const FileModelItem dom = d->buildDom(arguments, addCompilerSupportArguments,
level, clangFlags);
- if (dom.isNull())
+ if (!dom)
return false;
if (ReportHandler::isDebug(ReportHandler::MediumDebug))
- qCDebug(lcShiboken) << dom.data();
+ qCDebug(lcShiboken) << dom.get();
d->traverseDom(dom, apiExtractorFlags);
return true;
@@ -709,7 +742,7 @@ void AbstractMetaBuilder::setLogDirectory(const QString &logDir)
d->m_logDirectory.append(QDir::separator());
}
-void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls,
+void AbstractMetaBuilderPrivate::addAbstractMetaClass(const AbstractMetaClassPtr &cls,
const _CodeModelItem *item)
{
m_itemToClass.insert(item, cls);
@@ -723,23 +756,27 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls,
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
- const NamespaceModelItem &namespaceItem)
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
+ const NamespaceModelItem &namespaceItem)
{
- QString namespaceName = currentScope()->qualifiedName().join(colonColon());
+ QString namespaceName = currentScope()->qualifiedName().join(u"::"_s);
if (!namespaceName.isEmpty())
- namespaceName.append(colonColon());
+ namespaceName.append(u"::"_s);
namespaceName.append(namespaceItem->name());
if (TypeDatabase::instance()->isClassRejected(namespaceName)) {
- m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled);
- return nullptr;
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, QString{}});
+ return {};
}
auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName());
if (!type) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName)));
+ const QString rejectReason = msgNamespaceNoTypeEntry(namespaceItem, namespaceName);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, rejectReason});
return nullptr;
}
@@ -749,22 +786,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
}
// Continue populating namespace?
- AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type);
+ AbstractMetaClassPtr metaClass = AbstractMetaClass::findClass(m_metaClasses, type);
if (!metaClass) {
- metaClass = new AbstractMetaClass;
+ metaClass.reset(new AbstractMetaClass);
metaClass->setTypeEntry(type);
- addAbstractMetaClass(metaClass, namespaceItem.data());
+ addAbstractMetaClass(metaClass, namespaceItem.get());
if (auto extendsType = type->extends()) {
- AbstractMetaClass *extended = AbstractMetaClass::findClass(m_metaClasses, extendsType);
+ const auto extended = AbstractMetaClass::findClass(m_metaClasses, extendsType);
if (!extended) {
qCWarning(lcShiboken, "%s",
qPrintable(msgNamespaceToBeExtendedNotFound(extendsType->name(), extendsType->targetLangPackage())));
- return nullptr;
+ return {};
}
metaClass->setExtendedNamespace(extended);
}
} else {
- m_itemToClass.insert(namespaceItem.data(), metaClass);
+ m_itemToClass.insert(namespaceItem.get(), metaClass);
}
traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
@@ -773,11 +810,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
const ClassList &classes = namespaceItem->classes();
for (const ClassModelItem &cls : classes) {
- AbstractMetaClass *mjc = traverseClass(dom, cls, metaClass);
+ const auto mjc = traverseClass(dom, cls, metaClass);
if (mjc) {
metaClass->addInnerClass(mjc);
mjc->setEnclosingClass(metaClass);
- addAbstractMetaClass(mjc, cls.data());
+ addAbstractMetaClass(mjc, cls.get());
}
}
@@ -785,22 +822,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
// specific typedefs to be used as classes.
const TypeDefList typeDefs = namespaceItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass);
+ const auto cls = traverseTypeDef(dom, typeDef, metaClass);
if (cls) {
metaClass->addInnerClass(cls);
cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.data());
+ addAbstractMetaClass(cls, typeDef.get());
}
}
// Traverse namespaces recursively
for (const NamespaceModelItem &ni : namespaceItem->namespaces()) {
- AbstractMetaClass *mjc = traverseNamespace(dom, ni);
+ const auto mjc = traverseNamespace(dom, ni);
if (mjc) {
metaClass->addInnerClass(mjc);
mjc->setEnclosingClass(metaClass);
- m_classToItem.insert(mjc, ni.data()); // Add for enum lookup.
- m_itemToClass.insert(ni.data(), mjc);
+ m_classToItem.insert(mjc, ni.get()); // Add for enum lookup.
+ m_itemToClass.insert(ni.get(), mjc);
}
}
@@ -814,16 +851,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
std::optional<AbstractMetaEnum>
AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
- AbstractMetaClass *enclosing,
+ const AbstractMetaClassPtr &enclosing,
const QSet<QString> &enumsDeclarations)
{
- QString qualifiedName = enumItem->qualifiedName().join(colonColon());
+ QString qualifiedName = enumItem->qualifiedName().join(u"::"_s);
- TypeEntry *typeEntry = nullptr;
- const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr;
+ TypeEntryPtr typeEntry;
+ const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{};
if (enumItem->accessPolicy() == Access::Private) {
- typeEntry = new EnumTypeEntry(enumItem->qualifiedName().constLast(),
- QVersionNumber(0, 0), enclosingTypeEntry);
+ typeEntry.reset(new EnumTypeEntry(enumItem->qualifiedName().constLast(),
+ QVersionNumber(0, 0), enclosingTypeEntry));
TypeDatabase::instance()->addType(typeEntry);
} else if (enumItem->enumKind() != AnonymousEnum) {
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
@@ -833,7 +870,7 @@ std::optional<AbstractMetaEnum>
for (const EnumeratorModelItem &enumValue : enums) {
tmpQualifiedName.removeLast();
tmpQualifiedName << enumValue->name();
- qualifiedName = tmpQualifiedName.join(colonColon());
+ qualifiedName = tmpQualifiedName.join(u"::"_s);
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
if (typeEntry)
break;
@@ -850,65 +887,75 @@ std::optional<AbstractMetaEnum>
if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
if (typeEntry)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
- m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ m_rejectedEnums.insert({AbstractMetaBuilder::GenerationDisabled, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode();
if (!typeEntry) {
+ const QString rejectReason = msgNoEnumTypeEntry(enumItem, className);
if (rejectionWarning)
- qCWarning(lcShiboken, "%s", qPrintable(msgNoEnumTypeEntry(enumItem, className)));
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
if (!typeEntry->isEnum()) {
- if (rejectionWarning) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNoEnumTypeConflict(enumItem, className, typeEntry)));
- }
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ const QString rejectReason = msgNoEnumTypeConflict(enumItem, className, typeEntry);
+ if (rejectionWarning)
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
AbstractMetaEnum metaEnum;
metaEnum.setEnumKind(enumItem->enumKind());
+ metaEnum.setDeprecated(enumItem->isDeprecated());
+ metaEnum.setUnderlyingType(enumItem->underlyingType());
metaEnum.setSigned(enumItem->isSigned());
if (enumsDeclarations.contains(qualifiedName)
|| enumsDeclarations.contains(enumName)) {
metaEnum.setHasQEnumsDeclaration(true);
}
- auto *enumTypeEntry = static_cast<EnumTypeEntry *>(typeEntry);
+ auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry);
metaEnum.setTypeEntry(enumTypeEntry);
metaEnum.setAccess(enumItem->accessPolicy());
if (metaEnum.access() == Access::Private)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
-
+ // PYSIDE-2088, MSVC signedness issue in Qt
+ const bool castToUnsigned = enumItem->isSigned()
+ && enumTypeEntry->cppType().contains(u"unsigned"_s);
const EnumeratorList &enums = enumItem->enumerators();
- for (const EnumeratorModelItem &value : enums) {
+ for (const EnumeratorModelItem &valueItem : enums) {
AbstractMetaEnumValue metaEnumValue;
- metaEnumValue.setName(value->name());
+ metaEnumValue.setName(valueItem->name());
// Deciding the enum value...
- metaEnumValue.setStringValue(value->stringValue());
- metaEnumValue.setValue(value->value());
+ metaEnumValue.setStringValue(valueItem->stringValue());
+ const auto value = valueItem->value();
+ metaEnumValue.setValue(castToUnsigned ? value.toUnsigned() : value);
+ metaEnumValue.setDeprecated(valueItem->isDeprecated());
metaEnum.addEnumValue(metaEnumValue);
}
- if (!metaEnum.typeEntry()->include().isValid())
- setInclude(metaEnum.typeEntry(), enumItem->fileName());
+ if (!metaEnum.typeEntry()->include().isValid()) {
+ auto te = std::const_pointer_cast<EnumTypeEntry>(metaEnum.typeEntry());
+ setInclude(te, enumItem->fileName());
+ }
// Register all enum values on Type database
const bool isScopedEnum = enumItem->enumKind() == EnumClass;
const EnumeratorList &enumerators = enumItem->enumerators();
for (const EnumeratorModelItem &e : enumerators) {
- auto enumValue =
- new EnumValueTypeEntry(e->name(), e->stringValue(),
- enumTypeEntry, isScopedEnum,
- enumTypeEntry->version());
+ auto enumValue = std::make_shared<EnumValueTypeEntry>(e->name(), e->stringValue(),
+ enumTypeEntry, isScopedEnum,
+ enumTypeEntry->version());
TypeDatabase::instance()->addType(enumValue);
if (e->value().isNullValue())
enumTypeEntry->setNullValue(enumValue);
@@ -920,9 +967,31 @@ std::optional<AbstractMetaEnum>
return metaEnum;
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &,
- const TypeDefModelItem &typeDef,
- AbstractMetaClass *currentClass)
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
+{
+ auto result = traverseTypeDefHelper(dom, typeDef, currentClass);
+ if (!result && typeDef->type().isPlain()) {
+ const auto &type = typeDef->type();
+ QString fullName;
+ if (currentClass)
+ fullName += currentClass->qualifiedCppName() + "::"_L1;
+ fullName += typeDef->name();
+ QString targetName = typeDef->type().toString();
+ m_typedefTargetToName.insert(targetName, fullName);
+ const QByteArray normalized = QMetaObject::normalizedType(targetName.toUtf8().constData());
+ if (targetName != QLatin1StringView(normalized))
+ m_typedefTargetToName.insert(QString::fromUtf8(normalized), fullName);
+ }
+ return result;
+}
+
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDefHelper(const FileModelItem &,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
{
TypeDatabase *types = TypeDatabase::instance();
QString className = stripTemplateArgs(typeDef->name());
@@ -931,16 +1000,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
// we have an inner class
if (currentClass) {
fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName())
- + colonColon() + fullClassName;
+ + u"::"_s + fullClassName;
}
// If this is the alias for a primitive type
// we store the aliased type on the alias
// TypeEntry
- PrimitiveTypeEntry *ptype = types->findPrimitiveType(className);
+ const auto ptype = types->findPrimitiveType(className);
const auto &targetNames = typeDef->type().qualifiedName();
- PrimitiveTypeEntry *pTarget = targetNames.size() == 1
- ? types->findPrimitiveType(targetNames.constFirst()) : nullptr;
+ const auto pTarget = targetNames.size() == 1
+ ? types->findPrimitiveType(targetNames.constFirst()) : PrimitiveTypeEntryPtr{};
if (ptype) {
ptype->setReferencedTypeEntry(pTarget);
return nullptr;
@@ -948,9 +1017,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
// It is a (nested?) global typedef to a primitive type
// (like size_t = unsigned)? Add it to the type DB.
- if (pTarget && pTarget->basicReferencedNonBuiltinTypeEntry()->isCppPrimitive()
+ if (pTarget && isCppPrimitive(basicReferencedNonBuiltinTypeEntry(pTarget))
&& currentClass == nullptr) {
- auto *pte = new PrimitiveTypeEntry(className, {}, nullptr);
+ auto pte = std::make_shared<PrimitiveTypeEntry>(className, QVersionNumber{},
+ TypeEntryCPtr{});
pte->setReferencedTypeEntry(pTarget);
pte->setBuiltIn(true);
types->addType(pte);
@@ -958,11 +1028,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
}
// If we haven't specified anything for the typedef, then we don't care
- ComplexTypeEntry *type = types->findComplexType(fullClassName);
+ auto type = types->findComplexType(fullClassName);
if (!type)
return nullptr;
- auto *metaClass = new AbstractMetaClass;
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setTypeDef(true);
metaClass->setTypeEntry(type);
metaClass->setBaseClassNames(QStringList(typeDef->type().toString()));
@@ -981,8 +1051,8 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
{
const auto &entries = TypeDatabase::instance()->typedefEntries();
for (auto it = entries.begin(), end = entries.end(); it != end; ++it) {
- TypedefEntry *te = it.value();
- auto *metaClass = new AbstractMetaClass;
+ const TypedefEntryPtr &te = it.value();
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setTypeDef(true);
metaClass->setTypeEntry(te->target());
metaClass->setBaseClassNames(QStringList(te->sourceType()));
@@ -1008,9 +1078,9 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom,
+AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom,
const ClassModelItem &classItem,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
QString className = stripTemplateArgs(classItem->name());
QString fullClassName = className;
@@ -1018,20 +1088,24 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
// we have inner an class
if (currentClass) {
fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName())
- + colonColon() + fullClassName;
+ + u"::"_s + fullClassName;
}
- ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(fullClassName);
+ const auto type = TypeDatabase::instance()->findComplexType(fullClassName);
AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason;
if (TypeDatabase::instance()->isClassRejected(fullClassName)) {
reason = AbstractMetaBuilder::GenerationDisabled;
} else if (!type) {
- TypeEntry *te = TypeDatabase::instance()->findType(fullClassName);
- if (te && !te->isComplex())
+ TypeEntryPtr te = TypeDatabase::instance()->findType(fullClassName);
+ if (te && !te->isComplex()) {
reason = AbstractMetaBuilder::RedefinedToNotClass;
- else
+ // Set the default include file name
+ if (!te->include().isValid())
+ setInclude(te, classItem->fileName());
+ } else {
reason = AbstractMetaBuilder::NotInTypeSystem;
+ }
} else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
reason = AbstractMetaBuilder::GenerationDisabled;
}
@@ -1040,11 +1114,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
QTextStream(&fullClassName) << "anonymous struct at " << classItem->fileName()
<< ':' << classItem->startLine();
}
- m_rejectedClasses.insert(fullClassName, reason);
+ m_rejectedClasses.insert({reason, fullClassName, fullClassName, QString{}});
return nullptr;
}
- auto *metaClass = new AbstractMetaClass;
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setSourceLocation(classItem->sourceLocation());
metaClass->setTypeEntry(type);
if ((type->typeFlags() & ComplexTypeEntry::ForceAbstract) != 0)
@@ -1053,6 +1127,9 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
if (classItem->isFinal())
*metaClass += AbstractMetaClass::FinalCppClass;
+ if (classItem->classType() == CodeModel::Struct)
+ *metaClass += AbstractMetaClass::Struct;
+
QStringList baseClassNames;
const QList<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses();
for (const _ClassModelItem::BaseClass &baseClass : baseClasses) {
@@ -1072,15 +1149,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
}
TemplateParameterList template_parameters = classItem->templateParameters();
- TypeEntries template_args;
+ TypeEntryCList template_args;
template_args.clear();
- auto argumentParent = metaClass->typeEntry()->typeSystemTypeEntry();
- for (int i = 0; i < template_parameters.size(); ++i) {
+ auto argumentParent = typeSystemTypeEntry(metaClass->typeEntry());
+ for (qsizetype i = 0; i < template_parameters.size(); ++i) {
const TemplateParameterModelItem &param = template_parameters.at(i);
- auto param_type = new TemplateArgumentEntry(param->name(), type->version(),
+ auto param_type =
+ std::make_shared<TemplateArgumentEntry>(param->name(), type->version(),
argumentParent);
param_type->setOrdinal(i);
- template_args.append(param_type);
+ template_args.append(TypeEntryCPtr(param_type));
}
metaClass->setTemplateArguments(template_args);
@@ -1092,11 +1170,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
{
const ClassList &innerClasses = classItem->classes();
for (const ClassModelItem &ci : innerClasses) {
- AbstractMetaClass *cl = traverseClass(dom, ci, metaClass);
+ const auto cl = traverseClass(dom, ci, metaClass);
if (cl) {
cl->setEnclosingClass(metaClass);
metaClass->addInnerClass(cl);
- addAbstractMetaClass(cl, ci.data());
+ addAbstractMetaClass(cl, ci.get());
}
}
@@ -1106,10 +1184,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
// specific typedefs to be used as classes.
const TypeDefList typeDefs = classItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass);
+ const auto cls = traverseTypeDef(dom, typeDef, metaClass);
if (cls) {
cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.data());
+ addAbstractMetaClass(cls, typeDef.get());
}
}
@@ -1121,7 +1199,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
}
void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item,
- AbstractMetaClass *metaClass)
+ const AbstractMetaClassPtr &metaClass)
{
// Classes/Namespace members
traverseFields(item, metaClass);
@@ -1135,28 +1213,25 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item
void AbstractMetaBuilderPrivate::traverseClassMembers(const ClassModelItem &item)
{
- AbstractMetaClass *metaClass = m_itemToClass.value(item.data());
- if (!metaClass)
- return;
-
- // Class members
- traverseScopeMembers(item, metaClass);
+ const auto metaClass = m_itemToClass.value(item.get());
+ if (metaClass) // Class members
+ traverseScopeMembers(item, metaClass);
}
-void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const
{
const _CodeModelItem *item = m_classToItem.value(metaClass);
if (item == nullptr || item->kind() != _CodeModelItem::Kind_Class)
return;
- auto classItem = static_cast<const _ClassModelItem *>(item);
+ const auto *classItem = static_cast<const _ClassModelItem *>(item);
for (const auto &um : classItem->usingMembers()) {
QString className = um.className;
- int pos = className.indexOf(u'<'); // strip "QList<value>"
+ auto pos = className.indexOf(u'<'); // strip "QList<value>"
if (pos != -1)
className.truncate(pos);
- if (auto baseClass = metaClass->AbstractMetaClass::findBaseClass(className)) {
+ if (auto baseClass = findBaseClass(metaClass, className)) {
QString name = um.memberName;
- const int lastQualPos = name.lastIndexOf(colonColon());
+ const auto lastQualPos = name.lastIndexOf(u"::"_s);
if (lastQualPos != -1)
name.remove(0, lastQualPos + 2);
metaClass->addUsingMember({name, baseClass, um.access});
@@ -1170,7 +1245,7 @@ void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaCla
void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelItem &item)
{
- AbstractMetaClass *metaClass = m_itemToClass.value(item.data());
+ const auto metaClass = m_itemToClass.value(item.get());
if (!metaClass)
return;
@@ -1185,18 +1260,18 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelIt
static inline QString fieldSignatureWithType(const VariableModelItem &field)
{
- return field->name() + QStringLiteral(" -> ") + field->type().toString();
+ return field->name() + " -> "_L1 + field->type().toString();
}
static inline QString qualifiedFieldSignatureWithType(const QString &className,
const VariableModelItem &field)
{
- return className + colonColon() + fieldSignatureWithType(field);
+ return className + u"::"_s + fieldSignatureWithType(field);
}
std::optional<AbstractMetaField>
AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field,
- const AbstractMetaClass *cls)
+ const AbstractMetaClassCPtr &cls)
{
QString fieldName = field->name();
QString className = cls->typeEntry()->qualifiedCppName();
@@ -1210,8 +1285,9 @@ std::optional<AbstractMetaField>
QString rejectReason;
if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) {
- m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason,
- AbstractMetaBuilder::GenerationDisabled);
+ const QString signature = qualifiedFieldSignatureWithType(className, field);
+ m_rejectedFields.insert({AbstractMetaBuilder::GenerationDisabled,
+ signature, signature, rejectReason});
return {};
}
@@ -1224,7 +1300,7 @@ std::optional<AbstractMetaField>
auto metaType = translateType(fieldType, cls);
if (!metaType.has_value()) {
- const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
+ const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(u"::"_s);
if (cls->typeEntry()->generateCode()) {
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingField(field, cls->name(), type)));
@@ -1259,7 +1335,7 @@ static bool applyFieldModifications(AbstractMetaField *f)
}
void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item,
- AbstractMetaClass *metaClass)
+ const AbstractMetaClassPtr &metaClass)
{
const VariableList &variables = scope_item->variables();
for (const VariableModelItem &field : variables) {
@@ -1278,7 +1354,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
return;
TypeDatabase *types = TypeDatabase::instance();
- static const QRegularExpression operatorRegExp(QStringLiteral("^operator "));
+ static const QRegularExpression operatorRegExp("^operator "_L1);
Q_ASSERT(operatorRegExp.isValid());
QString castTo = metaFunction->name().remove(operatorRegExp).trimmed();
@@ -1287,7 +1363,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
if (castTo.startsWith(u"const "))
castTo.remove(0, 6);
- TypeEntry *retType = types->findType(castTo);
+ TypeEntryPtr retType = types->findType(castTo);
if (!retType)
return;
@@ -1299,7 +1375,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
AbstractMetaFunctionRawPtrList
AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
*constructorAttributes = {};
AbstractMetaFunctionRawPtrList result;
@@ -1311,10 +1387,10 @@ AbstractMetaFunctionRawPtrList
traverseOperatorFunction(function, currentClass);
} else if (function->isSpaceshipOperator() && !function->isDeleted()) {
if (currentClass)
- currentClass->addSynthesizedComparisonOperators();
+ AbstractMetaClass::addSynthesizedComparisonOperators(currentClass);
} else if (auto *metaFunction = traverseFunction(function, currentClass)) {
result.append(metaFunction);
- } else if (function->functionType() == CodeModel::Constructor) {
+ } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) {
auto arguments = function->arguments();
*constructorAttributes |= AbstractMetaClass::HasRejectedConstructor;
if (arguments.isEmpty() || arguments.constFirst()->defaultValue())
@@ -1324,8 +1400,8 @@ AbstractMetaFunctionRawPtrList
return result;
}
-void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
- AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::traverseFunctions(const ScopeModelItem& scopeItem,
+ const AbstractMetaClassPtr &metaClass)
{
AbstractMetaClass::Attributes constructorAttributes;
const AbstractMetaFunctionRawPtrList functions =
@@ -1334,7 +1410,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
for (AbstractMetaFunction *metaFunction : functions) {
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name());
if (propertyFunction.index >= 0) {
@@ -1367,21 +1443,20 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
metaFunction->setPropertySpecIndex(propertyFunction.index);
}
break;
+ case AbstractMetaClass::PropertyFunction::Notify:
+ if (metaFunction->isSignal()) {
+ *metaFunction += AbstractMetaFunction::PropertyNotify;
+ metaFunction->setPropertySpecIndex(propertyFunction.index);
+ }
}
}
- const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate();
- const bool isInvalidConstructor = metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
- && metaFunction->isPrivate();
- if (isInvalidConstructor)
+ if (metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
+ && metaFunction->isPrivate()) {
metaClass->setHasPrivateConstructor(true);
- if ((isInvalidDestructor || isInvalidConstructor)
- && !metaClass->hasNonPrivateConstructor()) {
- *metaClass += AbstractMetaClass::FinalInTargetLang;
- } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) {
- *metaClass -= AbstractMetaClass::FinalInTargetLang;
- metaClass->setHasNonPrivateConstructor(true);
}
+ if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT
+ metaClass->setHasNonPrivateConstructor(true);
if (!metaFunction->isDestructor()
&& !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) {
@@ -1392,7 +1467,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
if (metaFunction->isConversionOperator())
fixReturnTypeOfConversionOperator(metaFunction);
- metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
applyFunctionModifications(metaFunction);
} else if (metaFunction->isDestructor()) {
metaClass->setHasPrivateDestructor(metaFunction->isPrivate());
@@ -1408,7 +1483,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
fillAddedFunctions(metaClass);
}
-void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::fillAddedFunctions(const AbstractMetaClassPtr &metaClass)
{
// Add the functions added by the typesystem
QString errorMessage;
@@ -1421,12 +1496,12 @@ void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass
QString AbstractMetaBuilder::getSnakeCaseName(const QString &name)
{
- const int size = name.size();
+ const auto size = name.size();
if (size < 3)
return name;
QString result;
result.reserve(size + 4);
- for (int i = 0; i < size; ++i) {
+ for (qsizetype i = 0; i < size; ++i) {
const QChar c = name.at(i);
if (c.isUpper()) {
if (i > 0) {
@@ -1472,26 +1547,17 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction
func->setOriginalName(func->name());
func->setName(mod.renamedToName());
} else if (mod.isAccessModifier()) {
- funcRef -= AbstractMetaFunction::Friendly;
-
if (mod.isPublic())
funcRef.modifyAccess(Access::Public);
else if (mod.isProtected())
funcRef.modifyAccess(Access::Protected);
else if (mod.isPrivate())
funcRef.modifyAccess(Access::Private);
- else if (mod.isFriendly())
- funcRef += AbstractMetaFunction::Friendly;
}
-
- if (mod.isFinal())
- funcRef += AbstractMetaFunction::FinalInTargetLang;
- else if (mod.isNonFinal())
- funcRef -= AbstractMetaFunction::FinalInTargetLang;
}
}
-bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
+bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &metaClass)
{
if (metaClass->inheritanceDone())
return true;
@@ -1503,11 +1569,13 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
// we only support our own containers and ONLY if there is only one baseclass
if (baseClasses.size() == 1 && baseClasses.constFirst().contains(u'<')) {
TypeInfo info;
- ComplexTypeEntry* baseContainerType;
- AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType);
+ ComplexTypeEntryPtr baseContainerType;
+ const auto templ = findTemplateClass(baseClasses.constFirst(), metaClass,
+ &info, &baseContainerType);
if (templ) {
setupInheritance(templ);
- inheritTemplate(metaClass, templ, info);
+ if (!inheritTemplate(metaClass, templ, info))
+ return false;
metaClass->typeEntry()->setBaseContainerType(templ->typeEntry());
return true;
}
@@ -1524,15 +1592,15 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
return true;
}
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("template baseclass '%1' of '%2' is not known")
- .arg(baseClasses.constFirst(), metaClass->name());
+ qCWarning(lcShiboken, "template baseclass '%s' of '%s' is not known",
+ qPrintable(baseClasses.constFirst()),
+ qPrintable(metaClass->name()));
return false;
}
- TypeDatabase* types = TypeDatabase::instance();
+ auto *types = TypeDatabase::instance();
- for (const auto &baseClassName : baseClasses) {
+ for (const auto &baseClassName : baseClasses) {
if (!types->isClassRejected(baseClassName)) {
auto typeEntry = types->findType(baseClassName);
if (typeEntry == nullptr || !typeEntry->isComplex()) {
@@ -1561,7 +1629,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
} else {
QString message;
QTextStream(&message) << "Class \"" << defaultSuperclassName
- << "\" specified as \"default-superclass\" of \"" << metaClass->name()
+ << R"(" specified as "default-superclass" of ")" << metaClass->name()
<< "\" could not be found in the code model.";
qCWarning(lcShiboken, "%s", qPrintable(message));
}
@@ -1571,7 +1639,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
}
void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const QStringList &enumsDeclarations)
{
const EnumList &enums = scopeItem->enums();
@@ -1619,7 +1687,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunction
AbstractMetaFunction *
AbstractMetaBuilderPrivate::traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass /* = nullptr */,
+ const AbstractMetaClassPtr &metaClass /* = {} */,
QString *errorMessage)
{
auto returnType = translateType(addedFunc->returnType(), metaClass, {}, errorMessage);
@@ -1631,7 +1699,7 @@ AbstractMetaFunction *
return nullptr;
}
- auto metaFunction = new AbstractMetaFunction(addedFunc);
+ auto *metaFunction = new AbstractMetaFunction(addedFunc);
metaFunction->setType(returnType.value());
metaFunction->setFunctionType(functionTypeFromName(addedFunc->name()));
@@ -1688,7 +1756,8 @@ AbstractMetaFunction *
// Find the correct default values
const FunctionModificationList functionMods = metaFunction->modifications(metaClass);
- for (int i = 0; i < metaArguments.size(); ++i) {
+ applyCachedFunctionModifications(metaFunction, functionMods);
+ for (qsizetype i = 0; i < metaArguments.size(); ++i) {
AbstractMetaArgument &metaArg = metaArguments[i];
// use replace-default-expression for set default value
@@ -1703,7 +1772,7 @@ AbstractMetaFunction *
}
bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
QString *errorMessage)
{
AbstractMetaFunction *metaFunction =
@@ -1713,11 +1782,11 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
const AbstractMetaArgumentList fargs = metaFunction->arguments();
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
if (metaFunction->name() == metaClass->name()) {
metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
if (fargs.size() == 1) {
- const TypeEntry *te = fargs.constFirst().type().typeEntry();
+ const auto te = fargs.constFirst().type().typeEntry();
if (te->isCustom())
metaFunction->setExplicit(true);
if (te->name() == metaFunction->name())
@@ -1727,7 +1796,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
metaFunction->setDeclaringClass(metaClass);
metaFunction->setImplementingClass(metaClass);
- metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
metaClass->setHasNonPrivateConstructor(true);
return true;
}
@@ -1743,7 +1812,7 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, co
}
}
- for (int i = 0, size = arguments.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = arguments.size(); i < size; ++i) {
if (arguments.at(i).name().isEmpty())
arguments[i].setName(u"arg__"_s + QString::number(i + 1), false);
}
@@ -1763,7 +1832,7 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem
{
QString result = functionItem->type().toString() + u' ';
if (!className.isEmpty())
- result += className + colonColon();
+ result += className + u"::"_s;
result += functionSignature(functionItem);
return result;
}
@@ -1875,9 +1944,48 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func
return true;
}
+// Create the meta type for a view (std::string_view -> std::string)
+static AbstractMetaType createViewOnType(const AbstractMetaType &metaType,
+ const TypeEntryCPtr &viewOnTypeEntry)
+{
+ auto result = metaType;
+ result.setTypeEntry(viewOnTypeEntry);
+ if (!metaType.isContainer() || !viewOnTypeEntry->isContainer())
+ return result;
+ // For containers, when sth with several template parameters
+ // (std::span<T, int N>) is mapped onto a std::vector<T>,
+ // remove the superfluous template parameters and strip 'const'.
+ const auto vcte = std::static_pointer_cast<const ContainerTypeEntry>(viewOnTypeEntry);
+ const auto &instantiations = metaType.instantiations();
+ AbstractMetaTypeList viewInstantiations;
+ const auto size = std::min(vcte->templateParameterCount(), instantiations.size());
+ for (qsizetype i = 0; i < size; ++i) {
+ auto ins = instantiations.at(i);
+ ins.setConstant(false);
+ viewInstantiations.append(ins);
+ }
+ result.setInstantiations(viewInstantiations);
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::rejectFunction(const FunctionModelItem &functionItem,
+ const AbstractMetaClassPtr &currentClass,
+ AbstractMetaBuilder::RejectReason reason,
+ const QString &rejectReason)
+{
+ QString sortKey;
+ if (currentClass)
+ sortKey += currentClass->typeEntry()->qualifiedCppName() + u"::"_s;
+ sortKey += functionSignature(functionItem); // Sort without return type
+ const QString signatureWithType = functionItem->type().toString() + u' ' + sortKey;
+ m_rejectedFunctions.insert({reason, signatureWithType, sortKey, rejectReason});
+}
+
AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
+ const auto *tdb = TypeDatabase::instance();
+
if (!functionItem->templateParameters().isEmpty())
return nullptr;
@@ -1918,20 +2026,17 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
} // PySide extensions
- // Store original signature with unresolved typedefs for message/log purposes
- const QString originalQualifiedSignatureWithReturn =
- qualifiedFunctionSignatureWithType(functionItem, className);
-
QString rejectReason;
- if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isFunctionRejected(className, functionName, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
return nullptr;
}
- const QString &signature = functionSignature(functionItem);
- const bool rejected =
- TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason);
- if (rejected) {
+ const QString &signature = functionSignature(functionItem);
+ if (tdb->isFunctionRejected(className, signature, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).",
qPrintable(className), qPrintable(signature), qPrintable(rejectReason));
@@ -1942,46 +2047,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (functionItem->isFriend())
return nullptr;
- const bool deprecated = functionItem->isDeprecated();
+ const auto cppAttributes = functionItem->attributes();
+ const bool deprecated = cppAttributes.testFlag(FunctionAttribute::Deprecated);
if (deprecated && m_skipDeprecated) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + u" is deprecated."_s,
- AbstractMetaBuilder::GenerationDisabled);
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, u" is deprecated."_s);
return nullptr;
}
+ AbstractMetaFunction::Flags flags;
auto *metaFunction = new AbstractMetaFunction(functionName);
+ metaFunction->setCppAttributes(cppAttributes);
+ const QByteArray cSignature = signature.toUtf8();
+ const QString unresolvedSignature =
+ QString::fromUtf8(QMetaObject::normalizedSignature(cSignature.constData()));
+ metaFunction->setUnresolvedSignature(unresolvedSignature);
if (functionItem->isHiddenFriend())
- metaFunction->setFlags(AbstractMetaFunction::Flag::HiddenFriend);
+ flags.setFlag(AbstractMetaFunction::Flag::HiddenFriend);
metaFunction->setSourceLocation(functionItem->sourceLocation());
- if (deprecated)
- *metaFunction += AbstractMetaFunction::Deprecated;
// Additional check for assignment/move assignment down below
metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType()));
metaFunction->setConstant(functionItem->isConstant());
metaFunction->setExceptionSpecification(functionItem->exceptionSpecification());
- if (functionItem->isAbstract())
- *metaFunction += AbstractMetaFunction::Abstract;
-
- if (functionItem->isVirtual()) {
- *metaFunction += AbstractMetaFunction::VirtualCppMethod;
- if (functionItem->isOverride())
- *metaFunction += AbstractMetaFunction::OverriddenCppMethod;
- if (functionItem->isFinal())
- *metaFunction += AbstractMetaFunction::FinalCppMethod;
- } else {
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
- if (functionItem->isInvokable())
- *metaFunction += AbstractMetaFunction::Invokable;
-
- if (functionItem->isStatic()) {
- *metaFunction += AbstractMetaFunction::Static;
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
// Access rights
metaFunction->setAccess(functionItem->accessPolicy());
@@ -1991,25 +2080,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
metaFunction->setType(AbstractMetaType::createVoid());
break;
case AbstractMetaFunction::ConstructorFunction:
- metaFunction->setExplicit(functionItem->isExplicit());
metaFunction->setName(currentClass->name());
metaFunction->setType(AbstractMetaType::createVoid());
break;
default: {
TypeInfo returnType = functionItem->type();
- if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
delete metaFunction;
return nullptr;
}
- auto type = translateType(returnType, currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (functionItem->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto type = translateType(returnType, currentClass, flags, &errorMessage);
if (!type.has_value()) {
const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedReturnType, reason);
delete metaFunction;
return nullptr;
}
@@ -2020,6 +2114,14 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
ArgumentList arguments = functionItem->arguments();
+ // Add private signals for documentation purposes
+ if (!arguments.isEmpty()
+ && m_apiExtractorFlags.testFlag(ApiExtractorFlag::UsePySideExtensions)
+ && functionItem->functionType() == CodeModel::Signal
+ && arguments.constLast()->type().qualifiedName().constLast() == u"QPrivateSignal") {
+ flags.setFlag(AbstractMetaFunction::Flag::PrivateSignal);
+ arguments.removeLast();
+ }
if (arguments.size() == 1) {
ArgumentModelItem arg = arguments.at(0);
@@ -2028,33 +2130,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
arguments.pop_front();
}
- for (int i = 0; i < arguments.size(); ++i) {
+ for (qsizetype i = 0; i < arguments.size(); ++i) {
const ArgumentModelItem &arg = arguments.at(i);
- if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
delete metaFunction;
return nullptr;
}
- auto metaTypeO = translateType(arg->type(), currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (arg->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto metaTypeO = translateType(arg->type(), currentClass, flags, &errorMessage);
if (!metaTypeO.has_value()) {
// If an invalid argument has a default value, simply remove it
// unless the function is virtual (since the override in the
// wrapper can then not correctly be generated).
- if (arg->defaultValue() && !functionItem->isVirtual()) {
+ if (arg->defaultValue()
+ && !functionItem->attributes().testFlag(FunctionAttribute::Virtual)) {
if (!currentClass || currentClass->typeEntry()->generateCode()) {
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
+ qPrintable(msgStrippingArgument(functionItem, i, signature,
+ arg, errorMessage)));
}
break;
}
const QString reason = msgUnmatchedParameterType(arg, i, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
- + u": "_s + reason;
- m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedArgumentType, reason);
delete metaFunction;
return nullptr;
}
@@ -2065,10 +2174,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
auto viewOnTypeEntry = metaType.typeEntry()->viewOn();
if (viewOnTypeEntry != nullptr && metaType.indirections() == 0
&& metaType.arrayElementType() == nullptr
- && !metaType.hasInstantiations()) {
- auto viewOn = metaType;
- viewOn.setTypeEntry(viewOnTypeEntry);
- metaType.setViewOn(viewOn);
+ && (!metaType.hasInstantiations() || metaType.isContainer())) {
+ metaType.setViewOn(createViewOnType(metaType, viewOnTypeEntry));
}
AbstractMetaArgument metaArgument;
@@ -2084,15 +2191,10 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
? AbstractMetaFunction::findClassModifications(metaFunction, currentClass)
: AbstractMetaFunction::findGlobalModifications(metaFunction);
- for (const FunctionModification &mod : functionMods) {
- if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
- metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
- if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
- metaFunction->setAllowThreadModification(mod.allowThread());
- }
+ applyCachedFunctionModifications(metaFunction, functionMods);
// Find the correct default values
- for (int i = 0, size = metaArguments.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = metaArguments.size(); i < size; ++i) {
const ArgumentModelItem &arg = arguments.at(i);
AbstractMetaArgument &metaArg = metaArguments[i];
@@ -2146,35 +2248,39 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
}
}
+ metaFunction->setFlags(flags);
return metaFunction;
}
-static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName)
+static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClassCPtr &metaClass,
+ const QString& qualifiedName)
{
- const TypeEntry* type = nullptr;
- QStringList context = metaClass->qualifiedCppName().split(colonColon());
+ TypeEntryCPtr type;
+ QStringList context = metaClass->qualifiedCppName().split(u"::"_s);
while (!type && !context.isEmpty()) {
- type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName);
+ type = TypeDatabase::instance()->findType(context.join(u"::"_s) + u"::"_s + qualifiedName);
context.removeLast();
}
return type;
}
// Helper for findTypeEntries/translateTypeStatic()
-TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName,
- const QString &name,
- const AbstractMetaClass *currentClass,
- AbstractMetaBuilderPrivate *d)
+TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName,
+ const QString &name,
+ TranslateTypeFlags flags,
+ const AbstractMetaClassCPtr &currentClass,
+ AbstractMetaBuilderPrivate *d)
{
// 5.1 - Try first using the current scope
- if (currentClass) {
+ if (currentClass != nullptr
+ && !flags.testFlag(AbstractMetaBuilder::NoClassScopeLookup)) {
if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName))
return {type};
// 5.1.1 - Try using the class parents' scopes
if (d && !currentClass->baseClassNames().isEmpty()) {
const auto &baseClasses = d->getBaseClasses(currentClass);
- for (const AbstractMetaClass *cls : baseClasses) {
+ for (const auto &cls : baseClasses) {
if (auto type = findTypeEntryUsingContext(cls, qualifiedName))
return {type};
}
@@ -2198,7 +2304,7 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua
// of the parameters.
if (currentClass) {
const auto &template_args = currentClass->templateArguments();
- for (const TypeEntry *te : template_args) {
+ for (const auto &te : template_args) {
if (te->name() == qualifiedName)
return {te};
}
@@ -2208,13 +2314,15 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua
// Helper for translateTypeStatic() that calls findTypeEntriesHelper()
// and does some error checking.
-TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
- const QString &name,
- const AbstractMetaClass *currentClass,
- AbstractMetaBuilderPrivate *d,
- QString *errorMessage)
-{
- TypeEntries types = findTypeEntriesHelper(qualifiedName, name, currentClass, d);
+TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
+ const QString &name,
+ TranslateTypeFlags flags,
+ const AbstractMetaClassCPtr &currentClass,
+ AbstractMetaBuilderPrivate *d,
+ QString *errorMessage)
+{
+ TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, flags,
+ currentClass, d);
if (types.isEmpty()) {
if (errorMessage != nullptr)
*errorMessage = msgCannotFindTypeEntry(qualifiedName);
@@ -2224,9 +2332,11 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified
// Resolve entries added by metabuilder (for example, "GLenum") to match
// the signatures for modifications.
for (qsizetype i = 0, size = types.size(); i < size; ++i) {
- const auto *e = types.at(i);
- if (e->isPrimitive())
- types[i] = e->asPrimitive()->basicReferencedNonBuiltinTypeEntry();
+ const auto &e = types.at(i);
+ if (e->isPrimitive()) {
+ const auto pte = std::static_pointer_cast<const PrimitiveTypeEntry>(e);
+ types[i] = basicReferencedNonBuiltinTypeEntry(pte);
+ }
}
if (types.size() == 1)
@@ -2234,7 +2344,7 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified
const auto typeEntryType = types.constFirst()->type();
const bool sameType = std::all_of(types.cbegin() + 1, types.cend(),
- [typeEntryType](const TypeEntry *e) {
+ [typeEntryType](const TypeEntryCPtr &e) {
return e->type() == typeEntryType;
});
@@ -2257,10 +2367,10 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified
// Reverse lookup of AbstractMetaType representing a template specialization
// found during traversing function arguments to its type system typedef'ed
// class.
-const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const
+AbstractMetaClassCPtr AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const
{
if (t.hasInstantiations()) {
- auto pred = [t](const TypeClassEntry &e) { return e.type.equals(t); };
+ auto pred = [t](const TypeClassEntry &e) { return e.type == t; };
auto it = std::find_if(m_typeSystemTypeDefs.cbegin(), m_typeSystemTypeDefs.cend(), pred);
if (it != m_typeSystemTypeDefs.cend())
return it->klass;
@@ -2281,22 +2391,22 @@ static void synthesizeWarning(const AbstractMetaFunctionCPtr &f)
}
static AbstractMetaFunctionPtr
- addMethod(AbstractMetaClass *s, const AbstractMetaType &returnType,
+ addMethod(const AbstractMetaClassPtr &s, const AbstractMetaType &returnType,
const QString &name, bool isConst = true)
{
- AbstractMetaFunctionPtr function(new AbstractMetaFunction(name));
+ auto function = std::make_shared<AbstractMetaFunction>(name);
function->setType(returnType);
- s->addFunction(function);
+ AbstractMetaClass::addFunction(s, function);
function->setConstant(isConst);
synthesizeWarning(function);
return function;
}
static AbstractMetaFunctionPtr
- addMethod(AbstractMetaClass *s, const QString &returnTypeName,
+ addMethod(const AbstractMetaClassPtr &s, const QString &returnTypeName,
const QString &name, bool isConst = true)
{
- auto *typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName);
+ auto typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName);
Q_ASSERT(typeEntry);
AbstractMetaType returnType(typeEntry);
returnType.decideUsagePattern();
@@ -2304,8 +2414,8 @@ static AbstractMetaFunctionPtr
}
// Create the instantiation type of a smart pointer
-static AbstractMetaType instantiationType(const AbstractMetaClass *s,
- const SmartPointerTypeEntry *ste)
+static AbstractMetaType instantiationType(const AbstractMetaClassCPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
{
AbstractMetaType type(s->templateArguments().constFirst());
if (ste->smartPointerType() != TypeSystem::SmartPointerType::ValueHandle)
@@ -2315,8 +2425,8 @@ static AbstractMetaType instantiationType(const AbstractMetaClass *s,
}
// Create the pointee argument of a smart pointer constructor or reset()
-static AbstractMetaArgument pointeeArgument(const AbstractMetaClass *s,
- const SmartPointerTypeEntry *ste)
+static AbstractMetaArgument pointeeArgument(const AbstractMetaClassCPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
{
AbstractMetaArgument pointee;
pointee.setType(instantiationType(s, ste));
@@ -2326,7 +2436,8 @@ static AbstractMetaArgument pointeeArgument(const AbstractMetaClass *s,
// Add the smart pointer constructors. For MSVC, (when not specifying
// <system-header>), clang only sees the default constructor.
-static void fixSmartPointerConstructors(AbstractMetaClass *s, const SmartPointerTypeEntry *ste)
+static void fixSmartPointerConstructors(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
{
const auto ctors = s->queryFunctions(FunctionQueryOption::Constructors);
bool seenDefaultConstructor = false;
@@ -2339,23 +2450,24 @@ static void fixSmartPointerConstructors(AbstractMetaClass *s, const SmartPointer
}
if (!seenParameter) {
- AbstractMetaFunctionPtr constructor(new AbstractMetaFunction(s->name()));
+ auto constructor = std::make_shared<AbstractMetaFunction>(s->name());
constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction);
constructor->addArgument(pointeeArgument(s, ste));
- s->addFunction(constructor);
+ AbstractMetaClass::addFunction(s, constructor);
synthesizeWarning(constructor);
}
if (!seenDefaultConstructor) {
- AbstractMetaFunctionPtr constructor(new AbstractMetaFunction(s->name()));
+ auto constructor = std::make_shared<AbstractMetaFunction>(s->name());
constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction);
- s->addFunction(constructor);
+ AbstractMetaClass::addFunction(s, constructor);
synthesizeWarning(constructor);
}
}
// Similarly, add the smart pointer reset() functions
-static void fixSmartPointerReset(AbstractMetaClass *s, const SmartPointerTypeEntry *ste)
+static void fixSmartPointerReset(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
{
const QString resetMethodName = ste->resetMethod();
const auto functions = s->findFunctions(resetMethodName);
@@ -2369,21 +2481,22 @@ static void fixSmartPointerReset(AbstractMetaClass *s, const SmartPointerTypeEnt
}
if (!seenParameter) {
- AbstractMetaFunctionPtr f(new AbstractMetaFunction(resetMethodName));
+ auto f = std::make_shared<AbstractMetaFunction>(resetMethodName);
f->addArgument(pointeeArgument(s, ste));
- s->addFunction(f);
+ AbstractMetaClass::addFunction(s, f);
synthesizeWarning(f);
}
if (!seenParameterLess) {
- AbstractMetaFunctionPtr f(new AbstractMetaFunction(resetMethodName));
- s->addFunction(f);
+ auto f = std::make_shared<AbstractMetaFunction>(resetMethodName);
+ AbstractMetaClass::addFunction(s, f);
synthesizeWarning(f);
}
}
// Add the relevant missing smart pointer functions.
-static void fixSmartPointerClass(AbstractMetaClass *s, const SmartPointerTypeEntry *ste)
+static void fixSmartPointerClass(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
{
fixSmartPointerConstructors(s, ste);
@@ -2391,43 +2504,43 @@ static void fixSmartPointerClass(AbstractMetaClass *s, const SmartPointerTypeEnt
fixSmartPointerReset(s, ste);
const QString getterName = ste->getter();
- if (s->findFunction(getterName).isNull())
+ if (!s->findFunction(getterName))
addMethod(s, instantiationType(s, ste), getterName);
const QString refCountName = ste->refCountMethodName();
- if (!refCountName.isEmpty() && s->findFunction(refCountName).isNull())
+ if (!refCountName.isEmpty() && !s->findFunction(refCountName))
addMethod(s, u"int"_s, refCountName);
const QString valueCheckMethod = ste->valueCheckMethod();
- if (!valueCheckMethod.isEmpty() && s->findFunction(valueCheckMethod).isNull()) {
+ if (!valueCheckMethod.isEmpty() && !s->findFunction(valueCheckMethod)) {
auto f = addMethod(s, u"bool"_s, valueCheckMethod);
if (valueCheckMethod == u"operator bool")
f->setFunctionType(AbstractMetaFunction::ConversionOperator);
}
const QString nullCheckMethod = ste->nullCheckMethod();
- if (!nullCheckMethod.isEmpty() && s->findFunction(nullCheckMethod).isNull())
+ if (!nullCheckMethod.isEmpty() && !s->findFunction(nullCheckMethod))
addMethod(s, u"bool"_s, nullCheckMethod);
}
// Create a missing smart pointer class
-static AbstractMetaClass *createSmartPointerClass(const SmartPointerTypeEntry *ste,
- const AbstractMetaClassList &allClasses)
+static AbstractMetaClassPtr createSmartPointerClass(const SmartPointerTypeEntryCPtr &ste,
+ const AbstractMetaClassList &allClasses)
{
- auto *result = new AbstractMetaClass();
- result->setTypeEntry(const_cast<SmartPointerTypeEntry *>(ste));
- auto *templateArg = new TemplateArgumentEntry(u"T"_s, ste->version(),
- ste->typeSystemTypeEntry());
+ auto result = std::make_shared<AbstractMetaClass>();
+ result->setTypeEntry(std::const_pointer_cast<SmartPointerTypeEntry>(ste));
+ auto templateArg = std::make_shared<TemplateArgumentEntry>(u"T"_s, ste->version(),
+ typeSystemTypeEntry(ste));
result->setTemplateArguments({templateArg});
fixSmartPointerClass(result, ste);
- auto *enclosingTe = ste->parent();
+ auto enclosingTe = ste->parent();
if (!enclosingTe->isTypeSystem()) {
- auto *enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe);
- if (enclosing == nullptr)
+ const auto enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe);
+ if (!enclosing)
throw Exception(msgEnclosingClassNotFound(ste));
result->setEnclosingClass(enclosing);
auto inner = enclosing->innerClasses();
- inner.append(result);
+ inner.append(std::const_pointer_cast<const AbstractMetaClass>(result));
enclosing->setInnerClasses(inner);
}
return result;
@@ -2436,11 +2549,12 @@ static AbstractMetaClass *createSmartPointerClass(const SmartPointerTypeEntry *s
void AbstractMetaBuilderPrivate::fixSmartPointers()
{
const auto smartPointerTypes = TypeDatabase::instance()->smartPointerTypes();
- for (auto *ste : smartPointerTypes) {
- const AbstractMetaClass *smartPointerClass =
+ for (const auto &ste : smartPointerTypes) {
+ const auto smartPointerClass =
AbstractMetaClass::findClass(m_smartPointers, ste);
if (smartPointerClass) {
- fixSmartPointerClass(const_cast<AbstractMetaClass *>(smartPointerClass), ste);
+ fixSmartPointerClass(std::const_pointer_cast<AbstractMetaClass>(smartPointerClass),
+ ste);
} else {
qCWarning(lcShiboken, "Synthesizing smart pointer \"%s\"...",
qPrintable(ste->qualifiedCppName()));
@@ -2451,7 +2565,7 @@ void AbstractMetaBuilderPrivate::fixSmartPointers()
std::optional<AbstractMetaType>
AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
- const AbstractMetaClass *currentClass,
+ const AbstractMetaClassCPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessage)
{
@@ -2464,9 +2578,16 @@ static bool isNumber(const QString &s)
[](QChar c) { return c.isDigit(); });
}
+// A type entry relevant only for non type template "X<5>"
+static bool isNonTypeTemplateArgument(const TypeEntryCPtr &te)
+{
+ const auto type = te->type();
+ return type == TypeEntry::EnumValue || type == TypeEntry::ConstantValueType;
+}
+
std::optional<AbstractMetaType>
AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
- const AbstractMetaClass *currentClass,
+ const AbstractMetaClassCPtr &currentClass,
AbstractMetaBuilderPrivate *d,
TranslateTypeFlags flags,
QString *errorMessageIn)
@@ -2493,10 +2614,10 @@ std::optional<AbstractMetaType>
// the global scope when they are referenced from inside a namespace.
// This is a work around to fix this bug since fixing it in resolveType
// seemed non-trivial
- int i = d ? d->m_scopes.size() - 1 : -1;
+ qsizetype i = d ? d->m_scopes.size() - 1 : -1;
while (i >= 0) {
typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--));
- if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
+ if (typeInfo.qualifiedName().join(u"::"_s) != _typei.qualifiedName().join(u"::"_s))
break;
}
@@ -2520,7 +2641,7 @@ std::optional<AbstractMetaType>
bool isConstCharStarCase =
oneDimensionalArrayOfUnspecifiedSize
&& typeInfo.qualifiedName().size() == 1
- && typeInfo.qualifiedName().at(0) == QStringLiteral("char")
+ && typeInfo.qualifiedName().at(0) == "char"_L1
&& typeInfo.indirections() == 0
&& typeInfo.isConstant()
&& typeInfo.referenceType() == NoReference
@@ -2550,7 +2671,7 @@ std::optional<AbstractMetaType>
return {};
}
- for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
+ for (auto i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
AbstractMetaType arrayType;
arrayType.setArrayElementType(elementType.value());
const QString &arrayElement = typeInfo.arrayElements().at(i);
@@ -2563,8 +2684,9 @@ std::optional<AbstractMetaType>
arrayType.setArrayElementCount(int(elems));
}
auto elementTypeEntry = elementType->typeEntry();
- arrayType.setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(),
- elementTypeEntry->parent()));
+ auto at = std::make_shared<ArrayTypeEntry>(elementTypeEntry, elementTypeEntry->version(),
+ elementTypeEntry->parent());
+ arrayType.setTypeEntry(at);
arrayType.decideUsagePattern();
elementType = arrayType;
@@ -2583,7 +2705,7 @@ std::optional<AbstractMetaType>
return {};
}
- QString qualifiedName = qualifierList.join(colonColon());
+ QString qualifiedName = qualifierList.join(u"::"_s);
QString name = qualifierList.takeLast();
// 4. Special case QFlags (include instantiation in name)
@@ -2592,14 +2714,23 @@ std::optional<AbstractMetaType>
typeInfo.clearInstantiations();
}
- const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d, errorMessageIn);
+ TypeEntryCList types = findTypeEntries(qualifiedName, name, flags,
+ currentClass, d, errorMessageIn);
+ if (!flags.testFlag(AbstractMetaBuilder::TemplateArgument)) {
+ // Avoid clashes between QByteArray and enum value QMetaType::QByteArray
+ // unless we are looking for template arguments.
+ auto end = std::remove_if(types.begin(), types.end(),
+ isNonTypeTemplateArgument);
+ types.erase(end, types.end());
+ }
+
if (types.isEmpty()) {
if (errorMessageIn != nullptr)
*errorMessageIn = msgUnableToTranslateType(_typei, *errorMessageIn);
return {};
}
- const TypeEntry *type = types.constFirst();
+ TypeEntryCPtr type = types.constFirst();
const TypeEntry::Type typeEntryType = type->type();
AbstractMetaType metaType;
@@ -2610,15 +2741,18 @@ std::optional<AbstractMetaType>
metaType.setOriginalTypeDescription(_typei.toString());
const auto &templateArguments = typeInfo.instantiations();
- for (int t = 0, size = templateArguments.size(); t < size; ++t) {
+ for (qsizetype t = 0, size = templateArguments.size(); t < size; ++t) {
const TypeInfo &ti = templateArguments.at(t);
- auto targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
+ auto targType = translateTypeStatic(ti, currentClass, d,
+ flags | AbstractMetaBuilder::TemplateArgument,
+ &errorMessage);
// For non-type template parameters, create a dummy type entry on the fly
// as is done for classes.
if (!targType.has_value()) {
- const QString value = ti.qualifiedName().join(colonColon());
+ const QString value = ti.qualifiedName().join(u"::"_s);
if (isNumber(value)) {
- TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry());
+ auto module = typeSystemTypeEntry(type);
+ TypeDatabase::instance()->addConstantValueTypeEntry(value, module);
targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
}
}
@@ -2644,8 +2778,8 @@ std::optional<AbstractMetaType>
type = instantiationType;
} else {
auto it = std::find_if(types.cbegin(), types.cend(),
- [instantiationType](const TypeEntry *e) {
- auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e);
+ [instantiationType](const TypeEntryCPtr &e) {
+ auto smartPtr = std::static_pointer_cast<const SmartPointerTypeEntry>(e);
return smartPtr->matchesInstantiation(instantiationType);
});
if (it == types.cend()) {
@@ -2679,7 +2813,7 @@ std::optional<AbstractMetaType>
std::optional<AbstractMetaType>
AbstractMetaBuilder::translateType(const TypeInfo &_typei,
- AbstractMetaClass *currentClass,
+ const AbstractMetaClassPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessage)
{
@@ -2690,7 +2824,7 @@ std::optional<AbstractMetaType>
std::optional<AbstractMetaType>
AbstractMetaBuilder::translateType(const QString &t,
- AbstractMetaClass *currentClass,
+ const AbstractMetaClassPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessageIn)
{
@@ -2720,7 +2854,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
// This is a very lame way to handle expression evaluation,
// but it is not critical and will do for the time being.
- static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ static const QRegularExpression variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$"_L1);
Q_ASSERT(variableNameRegExp.isValid());
if (!variableNameRegExp.match(stringValue).hasMatch()) {
ok = true;
@@ -2733,7 +2867,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
return enumValue->value().value();
}
- for (const AbstractMetaEnum &metaEnum : qAsConst(m_globalEnums)) {
+ for (const AbstractMetaEnum &metaEnum : std::as_const(m_globalEnums)) {
auto ev = metaEnum.findEnumValue(stringValue);
if (ev.has_value()) {
ok = true;
@@ -2757,9 +2891,10 @@ static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidat
}
QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type,
- const QString &expr) const
+ const QString &expr,
+ const AbstractMetaClassCPtr &klass) const
{
- return d->fixEnumDefault(type, expr);
+ return d->fixEnumDefault(type, expr, klass);
}
void AbstractMetaBuilder::setCodeModelTestMode(bool b)
@@ -2770,7 +2905,7 @@ void AbstractMetaBuilder::setCodeModelTestMode(bool b)
// Helper to fix a simple default value (field or enum reference) in a
// class context.
QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr,
- const AbstractMetaClass *klass) const
+ const AbstractMetaClassCPtr &klass) const
{
const QString field = qualifyStaticField(klass, expr);
@@ -2789,7 +2924,7 @@ QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr,
// see TestResolveType::testFixDefaultArguments()
QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const AbstractMetaType &type,
- const AbstractMetaClass *implementingClass) const
+ const AbstractMetaClassCPtr &implementingClass) const
{
expr.replace(u'\n', u' '); // breaks signature parser
@@ -2797,13 +2932,13 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract
return expr;
if (type.isFlags() || type.isEnum()) {
- expr = fixEnumDefault(type, expr);
+ expr = fixEnumDefault(type, expr, implementingClass);
} else if (type.isContainer() && expr.contains(u'<')) {
// Expand a container of a nested class, fex
// "QList<FormatRange>()" -> "QList<QTextLayout::FormatRange>()"
if (type.instantiations().size() != 1)
return expr; // Only simple types are handled, not QMap<int, int>.
- auto *innerTypeEntry = type.instantiations().constFirst().typeEntry();
+ auto innerTypeEntry = type.instantiations().constFirst().typeEntry();
if (!innerTypeEntry->isComplex())
return expr;
const QString &qualifiedInnerTypeName = innerTypeEntry->qualifiedCppName();
@@ -2857,7 +2992,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract
}
}
// Is this a class constructor "Class(Field)"? Expand it.
- auto *te = type.typeEntry();
+ const auto te = type.typeEntry();
if (!te->isComplex())
return expr;
const QString &qualifiedTypeName = te->qualifiedCppName();
@@ -2872,7 +3007,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract
}
QString AbstractMetaBuilder::fixDefaultValue(const QString &expr, const AbstractMetaType &type,
- const AbstractMetaClass *c) const
+ const AbstractMetaClassCPtr &c) const
{
return d->fixDefaultValue(expr, type, c);
}
@@ -2883,23 +3018,24 @@ bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringL
return item && item->kind() == _EnumModelItem::__node_kind;
}
-AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
- const AbstractMetaClass *context,
- TypeInfo *info,
- ComplexTypeEntry **baseContainerType) const
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
+ const AbstractMetaClassCPtr &context,
+ TypeInfo *info,
+ ComplexTypeEntryPtr *baseContainerType) const
{
if (baseContainerType)
- *baseContainerType = nullptr;
- TypeDatabase* types = TypeDatabase::instance();
+ baseContainerType->reset();
+ auto *types = TypeDatabase::instance();
- QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon());
+ QStringList scope = context->typeEntry()->qualifiedCppName().split(u"::"_s);
QString errorMessage;
scope.removeLast();
- for (int i = scope.size(); i >= 0; --i) {
- QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString();
+ for (auto i = scope.size(); i >= 0; --i) {
+ QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(u"::"_s) + u"::"_s : QString();
QString completeName = prefix + name;
const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage);
- QString qualifiedName = parsed.qualifiedName().join(colonColon());
+ QString qualifiedName = parsed.qualifiedName().join(u"::"_s);
if (qualifiedName.isEmpty()) {
qWarning().noquote().nospace() << "Unable to parse type \"" << completeName
<< "\" while looking for template \"" << name << "\": " << errorMessage;
@@ -2908,8 +3044,8 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &
if (info)
*info = parsed;
- AbstractMetaClass *templ = nullptr;
- for (AbstractMetaClass *c : qAsConst(m_templates)) {
+ AbstractMetaClassPtr templ;
+ for (const auto &c : std::as_const(m_templates)) {
if (c->typeEntry()->name() == qualifiedName) {
templ = c;
break;
@@ -2930,7 +3066,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &
}
AbstractMetaClassCList
- AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const
+ AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClassCPtr &metaClass) const
{
// Shortcut if inheritance has already been set up
if (metaClass->inheritanceDone() || !metaClass->needsInheritanceSetup())
@@ -2938,11 +3074,9 @@ AbstractMetaClassCList
AbstractMetaClassCList baseClasses;
const QStringList &baseClassNames = metaClass->baseClassNames();
for (const QString& parent : baseClassNames) {
- AbstractMetaClass *cls = nullptr;
- if (parent.contains(u'<'))
- cls = findTemplateClass(parent, metaClass);
- else
- cls = AbstractMetaClass::findClass(m_metaClasses, parent);
+ const auto cls = parent.contains(u'<')
+ ? findTemplateClass(parent, metaClass)
+ : AbstractMetaClass::findClass(m_metaClasses, parent);
if (cls)
baseClasses << cls;
@@ -2962,7 +3096,7 @@ std::optional<AbstractMetaType>
returned.setOriginalTemplateType(metaType);
if (returned.typeEntry()->isTemplateArgument()) {
- const auto *tae = static_cast<const TemplateArgumentEntry*>(returned.typeEntry());
+ const auto tae = std::static_pointer_cast<const TemplateArgumentEntry>(returned.typeEntry());
// If the template is intantiated with void we special case this as rejecting the functions that use this
// parameter from the instantiation.
@@ -2992,77 +3126,104 @@ std::optional<AbstractMetaType>
return returned;
}
-AbstractMetaClass *
- AbstractMetaBuilder::inheritTemplateClass(ComplexTypeEntry *te,
- const AbstractMetaClass *templateClass,
+AbstractMetaClassPtr
+ AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags)
{
- auto result = std::make_unique<AbstractMetaClass>();
+ auto result = std::make_shared<AbstractMetaClass>();
result->setTypeDef(true);
result->setTypeEntry(te);
- if (!AbstractMetaBuilderPrivate::inheritTemplate(result.get(), templateClass,
+ if (!AbstractMetaBuilderPrivate::inheritTemplate(result, templateClass,
templateTypes, flags)) {
- return nullptr;
+ return {};
}
- AbstractMetaBuilderPrivate::inheritTemplateFunctions(result.get());
- return result.release();
+ AbstractMetaBuilderPrivate::inheritTemplateFunctions(result);
+ return result;
}
-bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
- const AbstractMetaClass *templateClass,
+
+static std::optional<AbstractMetaType>
+ inheritTemplateParameter(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
+ const TypeInfo &info, QString *errorMessage)
+{
+ QString typeName = info.qualifiedName().join("::"_L1);
+ TypeDatabase *typeDb = TypeDatabase::instance();
+ TypeEntryPtr t;
+ // Check for a non-type template integer parameter, that is, for a base
+ // "template <int R, int C> Matrix<R, C>" and subclass
+ // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of
+ // EnumValueTypeEntry for the integer values encountered on the fly.
+ if (isNumber(typeName)) {
+ t = typeDb->findType(typeName);
+ if (!t) {
+ auto parent = typeSystemTypeEntry(subclass->typeEntry());
+ t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
+ }
+ } else {
+ QStringList possibleNames;
+ possibleNames << subclass->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << templateClass->qualifiedCppName() + "::"_L1 + typeName;
+ if (subclass->enclosingClass())
+ possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << typeName;
+
+ for (const QString &possibleName : std::as_const(possibleNames)) {
+ t = typeDb->findType(possibleName);
+ if (t)
+ break;
+ }
+ }
+
+ if (!t) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "The corresponding type was not found in the typesystem.");
+ return std::nullopt;
+ }
+
+ if (t->isContainer()) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "Template inheritance from nested containers is not supported");
+ return std::nullopt;
+ }
+ AbstractMetaType result(t);
+ result.setConstant(info.isConstant());
+ result.setReferenceType(info.referenceType());
+ result.setIndirectionsV(info.indirectionsV());
+ result.decideUsagePattern();
+ return result;
+}
+
+bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
const TypeInfo &info)
{
AbstractMetaTypeList templateTypes;
+ QString errorMessage;
for (const TypeInfo &i : info.instantiations()) {
- QString typeName = i.qualifiedName().join(colonColon());
- TypeDatabase *typeDb = TypeDatabase::instance();
- TypeEntry *t = nullptr;
- // Check for a non-type template integer parameter, that is, for a base
- // "template <int R, int C> Matrix<R, C>" and subclass
- // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of
- // EnumValueTypeEntry for the integer values encountered on the fly.
- if (isNumber(typeName)) {
- t = typeDb->findType(typeName);
- if (!t) {
- auto parent = subclass->typeEntry()->typeSystemTypeEntry();
- t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
- }
+ const auto typeO = inheritTemplateParameter(subclass, templateClass, i, &errorMessage);
+ if (typeO.has_value()) {
+ templateTypes.append(typeO.value());
} else {
- QStringList possibleNames;
- possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
- possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
- if (subclass->enclosingClass())
- possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName;
- possibleNames << typeName;
-
- for (const QString &possibleName : qAsConst(possibleNames)) {
- t = typeDb->findType(possibleName);
- if (t)
- break;
- }
- }
-
- if (t) {
- AbstractMetaType temporaryType(t);
- temporaryType.setConstant(i.isConstant());
- temporaryType.setReferenceType(i.referenceType());
- temporaryType.setIndirectionsV(i.indirectionsV());
- temporaryType.decideUsagePattern();
- templateTypes << temporaryType;
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "Ignoring template parameter " << typeName << " from "
- << info.toString() << ". The corresponding type was not found in the typesystem.";
+ errorMessage = msgInheritTemplateIssue(subclass, info, errorMessage);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
}
}
+ if (templateTypes.isEmpty()) {
+ errorMessage = msgInheritTemplateIssue(subclass, info,
+ "No template parameters could be inherited"_L1);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
+ return false;
+ }
return inheritTemplate(subclass, templateClass, templateTypes);
}
-bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
- const AbstractMetaClass *templateClass,
+bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags)
{
@@ -3112,11 +3273,11 @@ AbstractMetaFunctionPtr
AbstractMetaFunctionPtr
AbstractMetaBuilderPrivate::inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass)
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass)
{
AbstractMetaFunctionPtr f = inheritTemplateFunction(function, templateTypes);
- if (f.isNull())
+ if (!f)
return {};
// There is no base class in the target language to inherit from here, so
@@ -3133,10 +3294,10 @@ AbstractMetaFunctionPtr
f->setOriginalName(subclass->name());
}
- ComplexTypeEntry *te = subclass->typeEntry();
- FunctionModificationList mods = function->modifications(templateClass);
- for (int i = 0; i < mods.size(); ++i) {
- FunctionModification mod = mods.at(i);
+ ComplexTypeEntryPtr te = subclass->typeEntry();
+ const FunctionModificationList mods = function->modifications(templateClass);
+
+ for (auto mod : mods) {
mod.setSignature(f->minimalSignature());
// If we ever need it... Below is the code to do
@@ -3170,8 +3331,8 @@ AbstractMetaFunctionPtr
AbstractMetaFunctionPtr
AbstractMetaBuilder::inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass)
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass)
{
return AbstractMetaBuilderPrivate::inheritTemplateMember(function, templateTypes,
templateClass, subclass);
@@ -3179,8 +3340,8 @@ AbstractMetaFunctionPtr
static bool doInheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
const AbstractMetaFunctionCList &existingSubclassFuncs,
- const AbstractMetaClass *templateBaseClass,
- const AbstractMetaClass *subclass)
+ const AbstractMetaClassCPtr &templateBaseClass,
+ const AbstractMetaClassCPtr &subclass)
{
// If the function is modified or the instantiation has an equally named
// function we are shadowing, so we need to skip it (unless the subclass
@@ -3193,7 +3354,7 @@ static bool doInheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
|| subclass->isUsingMember(templateBaseClass, function->name(), Access::Protected);
}
-void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *subclass)
+void AbstractMetaBuilderPrivate::inheritTemplateFunctions(const AbstractMetaClassPtr &subclass)
{
auto templateClass = subclass->templateBaseClass();
@@ -3214,8 +3375,8 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
templateClass, subclass)) {
AbstractMetaFunctionCPtr f = inheritTemplateMember(function, templateTypes,
templateClass, subclass);
- if (!f.isNull())
- subclass->addFunction(f);
+ if (f)
+ AbstractMetaClass::addFunction(subclass, f);
}
}
@@ -3225,8 +3386,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
for (const AbstractMetaField &field : templateClassFields) {
// If the field is modified or the instantiation has a field named
// the same as an existing field we have shadowing, so we need to skip it.
- if (field.isModifiedRemoved(TypeSystem::All)
- || field.isStatic()
+ if (field.isModifiedRemoved() || field.isStatic()
|| AbstractMetaField::find(existingSubclassFields, field.name()).has_value()) {
continue;
}
@@ -3241,7 +3401,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
}
}
-void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
+void AbstractMetaBuilderPrivate::parseQ_Properties(const AbstractMetaClassPtr &metaClass,
const QStringList &declarations)
{
const QStringList scopes = currentScope()->qualifiedName();
@@ -3252,7 +3412,7 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
if (spec.has_value()) {
spec->setIndex(i);
metaClass->addPropertySpec(spec.value());
- } else {
+ } else if (!errorMessage.isEmpty()) {
QString message;
QTextStream str(&message);
str << metaClass->sourceLocation() << errorMessage;
@@ -3281,24 +3441,35 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
}
}
-void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClass *cls)
+void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClassCPtr &cls)
{
const auto &convOps = cls->operatorOverloads(OperatorQueryOption::ConversionOp);
for (const auto &func : convOps) {
if (func->isModifiedRemoved())
continue;
- AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry());
+ const auto metaClass =
+ AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry());
if (!metaClass)
continue;
metaClass->addExternalConversionOperator(func);
}
- for (auto *innerClass : cls->innerClasses())
+ for (const auto &innerClass : cls->innerClasses())
setupExternalConversion(innerClass);
}
static void writeRejectLogFile(const QString &name,
- const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
-{
+ const AbstractMetaBuilderPrivate::RejectSet &rejects)
+{
+ static const QHash<AbstractMetaBuilder::RejectReason, QByteArray> descriptions ={
+ {AbstractMetaBuilder::NotInTypeSystem, "Not in type system"_ba},
+ {AbstractMetaBuilder::GenerationDisabled, "Generation disabled by type system"_ba},
+ {AbstractMetaBuilder::RedefinedToNotClass, "Type redefined to not be a class"_ba},
+ {AbstractMetaBuilder::UnmatchedReturnType, "Unmatched return type"_ba},
+ {AbstractMetaBuilder::UnmatchedArgumentType, "Unmatched argument type"_ba},
+ {AbstractMetaBuilder::UnmatchedOperator, "Unmatched operator"_ba},
+ {AbstractMetaBuilder::Deprecated, "Deprecated"_ba}
+ };
+
QFile f(name);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
qCWarning(lcShiboken, "%s", qPrintable(msgCannotOpenForWriting(f)));
@@ -3307,53 +3478,19 @@ static void writeRejectLogFile(const QString &name,
QTextStream s(&f);
-
- for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) {
- s << QByteArray(72, '*') << '\n';
- switch (reason) {
- case AbstractMetaBuilder::NotInTypeSystem:
- s << "Not in type system";
- break;
- case AbstractMetaBuilder::GenerationDisabled:
- s << "Generation disabled by type system";
- break;
- case AbstractMetaBuilder::RedefinedToNotClass:
- s << "Type redefined to not be a class";
- break;
-
- case AbstractMetaBuilder::UnmatchedReturnType:
- s << "Unmatched return type";
- break;
-
- case AbstractMetaBuilder::UnmatchedArgumentType:
- s << "Unmatched argument type";
- break;
-
- case AbstractMetaBuilder::ApiIncompatible:
- s << "Incompatible API";
- break;
-
- case AbstractMetaBuilder::Deprecated:
- s << "Deprecated";
- break;
-
- default:
- s << "unknown reason";
- break;
- }
-
- s << Qt::endl;
-
- for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
- it != rejects.constEnd(); ++it) {
- if (it.value() != reason)
- continue;
- s << " - " << it.key() << Qt::endl;
+ int lastReason = -1;
+ for (const auto &e : rejects) {
+ if (e.reason != lastReason) {
+ const QByteArray description = descriptions.value(e.reason, "Unknown reason"_ba);
+ const QByteArray underline(description.size(), '*');
+ if (lastReason != -1)
+ s << '\n';
+ s << underline << '\n' << description << '\n' << underline << "\n\n";
+ lastReason = e.reason;
}
- s << QByteArray(72, '*') << "\n\n";
+ s << " - " << e << '\n';
}
-
}
void AbstractMetaBuilderPrivate::dumpLog() const
@@ -3368,10 +3505,10 @@ void AbstractMetaBuilderPrivate::dumpLog() const
// AbstractMetaClassList/AbstractMetaClassCList.
// Add a dependency of the class associated with typeEntry on clazz.
template <class MetaClass>
-static bool addClassDependency(const QList<MetaClass *> &classList,
- const TypeEntry *typeEntry,
- MetaClass *clazz,
- Graph<MetaClass *> *graph)
+static bool addClassDependency(const QList<std::shared_ptr<MetaClass> > &classList,
+ const TypeEntryCPtr &typeEntry,
+ std::shared_ptr<MetaClass> clazz,
+ Graph<std::shared_ptr<MetaClass> > *graph)
{
if (!typeEntry->isComplex() || typeEntry == clazz->typeEntry())
return false;
@@ -3382,10 +3519,11 @@ static bool addClassDependency(const QList<MetaClass *> &classList,
}
template <class MetaClass>
-static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classList,
- const Dependencies &additionalDependencies)
+static QList<std::shared_ptr<MetaClass> >
+ topologicalSortHelper(const QList<std::shared_ptr<MetaClass> > &classList,
+ const Dependencies &additionalDependencies)
{
- Graph<MetaClass *> graph(classList.cbegin(), classList.cend());
+ Graph<std::shared_ptr<MetaClass> > graph(classList.cbegin(), classList.cend());
for (const auto &dep : additionalDependencies) {
if (!graph.addEdge(dep.parent, dep.child)) {
@@ -3395,14 +3533,14 @@ static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classL
}
}
- for (auto *clazz : classList) {
+ for (const auto &clazz : classList) {
if (auto enclosingC = clazz->enclosingClass()) {
- auto enclosing = const_cast<AbstractMetaClass *>(enclosingC);
+ const auto enclosing = std::const_pointer_cast<MetaClass>(enclosingC);
graph.addEdge(enclosing, clazz);
}
- for (auto baseClass : clazz->baseClasses())
- graph.addEdge(const_cast<MetaClass *>(baseClass), clazz);
+ for (const auto &baseClass : clazz->baseClasses())
+ graph.addEdge(std::const_pointer_cast<MetaClass>(baseClass), clazz);
for (const auto &func : clazz->functions()) {
const AbstractMetaArgumentList &arguments = func->arguments();
@@ -3430,16 +3568,22 @@ static QList<MetaClass *> topologicalSortHelper(const QList<MetaClass *> &classL
if (!result.isValid() && graph.nodeCount()) {
QTemporaryFile tempFile(QDir::tempPath() + u"/cyclic_depXXXXXX.dot"_s);
tempFile.setAutoRemove(false);
- tempFile.open();
- graph.dumpDot(tempFile.fileName(),
- [] (const AbstractMetaClass *c) { return c->name(); });
+ const bool ok = tempFile.open();
+ if (ok) {
+ graph.dumpDot(tempFile.fileName(),
+ [] (const AbstractMetaClassCPtr &c) { return c->name(); });
+ }
QString message;
QTextStream str(&message);
str << "Cyclic dependency of classes found:";
- for (auto c : result.cyclic)
+ for (const auto &c : result.cyclic)
str << ' ' << c->name();
- str << ". Graph can be found at \"" << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ str << '.';
+ if (ok) {
+ str << " Graph can be found at \""
+ << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ }
qCWarning(lcShiboken, "%s", qPrintable(message));
}
@@ -3473,8 +3617,8 @@ void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item)
}
}
if (candidates.size() > 1) {
- NamespaceModelItem joined(new _NamespaceModelItem(m_scopes.constLast()->model(),
- name, _CodeModelItem::Kind_Namespace));
+ auto joined = std::make_shared<_NamespaceModelItem>(m_scopes.constLast()->model(),
+ name, _CodeModelItem::Kind_Namespace);
joined->setScope(item->scope());
for (const auto &n : candidates)
joined->appendNamespace(*n);
@@ -3528,13 +3672,13 @@ static bool matchHeader(const QString &headerPath, const QString &fileName)
#else
static const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
#endif
- const int pathSize = headerPath.size();
+ const auto pathSize = headerPath.size();
return fileName.size() > pathSize
&& isFileSystemSlash(fileName.at(pathSize))
&& fileName.startsWith(headerPath, caseSensitivity);
}
-void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &path) const
+void AbstractMetaBuilderPrivate::setInclude(const TypeEntryPtr &te, const QString &path) const
{
auto it = m_resolveIncludeHash.find(path);
if (it == m_resolveIncludeHash.end()) {
@@ -3582,9 +3726,9 @@ void AbstractMetaBuilder::formatDebug(QDebug &debug) const
debug << "m_globalHeader=" << d->m_globalHeaders;
debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n");
debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n");
- if (const int scopeCount = d->m_scopes.size()) {
+ if (const auto scopeCount = d->m_scopes.size()) {
debug << "\n scopes[" << scopeCount << "]=(";
- for (int i = 0; i < scopeCount; ++i) {
+ for (qsizetype i = 0; i < scopeCount; ++i) {
if (i)
debug << ", ";
_CodeModelItem::formatKind(debug, d->m_scopes.at(i)->kind());
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
index 563db8f6e..cbd8c7034 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h
@@ -8,6 +8,7 @@
#include "apiextractorflags.h"
#include "header_paths.h"
#include "typesystem_enums.h"
+#include "typesystem_typedefs.h"
#include "clangparser/compilersupport.h"
@@ -28,13 +29,15 @@ class TypeEntry;
class AbstractMetaBuilder
{
public:
+ Q_DISABLE_COPY_MOVE(AbstractMetaBuilder)
+
enum RejectReason {
NotInTypeSystem,
GenerationDisabled,
RedefinedToNotClass,
UnmatchedArgumentType,
UnmatchedReturnType,
- ApiIncompatible,
+ UnmatchedOperator,
Deprecated,
NoReason
};
@@ -50,7 +53,8 @@ public:
AbstractMetaClassList takeSmartPointers();
const AbstractMetaFunctionCList &globalFunctions() const;
const AbstractMetaEnumList &globalEnums() const;
- const QHash<const TypeEntry *, AbstractMetaEnum> &typeEntryToEnumsHash() const;
+ const QHash<TypeEntryCPtr, AbstractMetaEnum> &typeEntryToEnumsHash() const;
+ const QMultiHash<QString, QString> &typedefTargetToName() const;
bool build(const QByteArrayList &arguments,
ApiExtractorFlags apiExtractorFlags = {},
@@ -74,15 +78,17 @@ public:
void setApiExtractorFlags(ApiExtractorFlags flags);
enum TranslateTypeFlag {
- DontResolveType = 0x1
+ DontResolveType = 0x1,
+ TemplateArgument = 0x2,
+ NoClassScopeLookup = 0x4
};
Q_DECLARE_FLAGS(TranslateTypeFlags, TranslateTypeFlag);
static std::optional<AbstractMetaType>
- translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass = nullptr,
+ translateType(const TypeInfo &_typei, const AbstractMetaClassPtr &currentClass = {},
TranslateTypeFlags flags = {}, QString *errorMessage = nullptr);
static std::optional<AbstractMetaType>
- translateType(const QString &t, AbstractMetaClass *currentClass = nullptr,
+ translateType(const QString &t, const AbstractMetaClassPtr &currentClass = {},
TranslateTypeFlags flags = {}, QString *errorMessage = nullptr);
/// Performs a template specialization of the function.
@@ -93,9 +99,9 @@ public:
inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes);
- static AbstractMetaClass *
- inheritTemplateClass(ComplexTypeEntry *te,
- const AbstractMetaClass *templateClass,
+ static AbstractMetaClassPtr
+ inheritTemplateClass(const ComplexTypeEntryPtr &te,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags = {});
@@ -108,23 +114,24 @@ public:
static AbstractMetaFunctionPtr
inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass);
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass);
static QString getSnakeCaseName(const QString &name);
// Names under which an item will be registered to Python depending on snakeCase
static QStringList definitionNames(const QString &name,
TypeSystem::SnakeCase snakeCase);
- static QString resolveScopePrefix(const AbstractMetaClass *scope,
+ static QString resolveScopePrefix(const AbstractMetaClassCPtr &scope,
QStringView value);
static bool dontFixDefaultValue(QStringView expr);
// For testing purposes
QString fixDefaultValue(const QString &expr, const AbstractMetaType &type,
- const AbstractMetaClass *) const;
- QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const;
+ const AbstractMetaClassCPtr &) const;
+ QString fixEnumDefault(const AbstractMetaType &type, const QString &expr,
+ const AbstractMetaClassCPtr & = {}) const;
static void setCodeModelTestMode(bool b);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
index f41104a77..68eef737a 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_helpers.cpp
@@ -9,6 +9,8 @@
#include "enumtypeentry.h"
#include "flagstypeentry.h"
+using namespace Qt::StringLiterals;
+
using QStringViewList = QList<QStringView>;
// Return a prefix to fully qualify value, eg:
@@ -19,7 +21,7 @@ static QString resolveScopePrefixHelper(const QStringViewList &scopeList,
{
QString name;
for (qsizetype i = scopeList.size() - 1 ; i >= 0; --i) {
- const QString prefix = scopeList.at(i).toString() + u"::"_qs;
+ const QString prefix = scopeList.at(i).toString() + u"::"_s;
if (value.startsWith(prefix))
name.clear();
else
@@ -28,14 +30,14 @@ static QString resolveScopePrefixHelper(const QStringViewList &scopeList,
return name;
}
-QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope,
+QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClassCPtr &scope,
QStringView value)
{
if (!scope)
return {};
const QString &qualifiedCppName = scope->qualifiedCppName();
const QStringViewList scopeList =
- QStringView{qualifiedCppName}.split(u"::"_qs, Qt::SkipEmptyParts);
+ QStringView{qualifiedCppName}.split(u"::"_s, Qt::SkipEmptyParts);
return resolveScopePrefixHelper(scopeList, value);
}
@@ -43,13 +45,13 @@ QString AbstractMetaBuilder::resolveScopePrefix(const AbstractMetaClass *scope,
static QString resolveEnumValueScopePrefix(const AbstractMetaEnum &metaEnum,
QStringView value)
{
- const AbstractMetaClass *scope = metaEnum.enclosingClass();
+ AbstractMetaClassCPtr scope = metaEnum.enclosingClass();
if (!scope)
return {}; // global enum, value should work as is
const QString &qualifiedCppName = scope->qualifiedCppName();
const QString &enumName = metaEnum.name();
QStringViewList parts =
- QStringView{qualifiedCppName}.split(u"::"_qs, Qt::SkipEmptyParts);
+ QStringView{qualifiedCppName}.split(u"::"_s, Qt::SkipEmptyParts);
// Append the type (as required for enum classes) unless it is an anonymous enum.
if (!metaEnum.isAnonymous())
parts.append(QStringView{enumName});
@@ -83,21 +85,26 @@ static bool isFloatConstant(const QStringView expr)
// to the default value, making it usable from Python wrapper code outside the
// owner class hierarchy. See TestEnum::testEnumDefaultValues().
QString AbstractMetaBuilderPrivate::fixEnumDefault(const AbstractMetaType &type,
- const QString &expr) const
+ const QString &expr,
+ const AbstractMetaClassCPtr &klass) const
{
// QFlags construct from integers, do not fix that
if (isIntegerConstant(expr))
return expr;
- const auto *typeEntry = type.typeEntry();
- const EnumTypeEntry *enumTypeEntry = nullptr;
- const FlagsTypeEntry *flagsTypeEntry = nullptr;
+ const QString field = qualifyStaticField(klass, expr);
+ if (!field.isEmpty())
+ return field;
+
+ const auto typeEntry = type.typeEntry();
+ EnumTypeEntryCPtr enumTypeEntry;
+ FlagsTypeEntryCPtr flagsTypeEntry;
if (typeEntry->isFlags()) {
- flagsTypeEntry = static_cast<const FlagsTypeEntry *>(typeEntry);
+ flagsTypeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry);
enumTypeEntry = flagsTypeEntry->originator();
} else {
Q_ASSERT(typeEntry->isEnum());
- enumTypeEntry = static_cast<const EnumTypeEntry *>(typeEntry);
+ enumTypeEntry = std::static_pointer_cast<const EnumTypeEntry>(typeEntry);
}
// Use the enum's qualified name (would otherwise be "QFlags<Enum>")
if (!enumTypeEntry->qualifiedCppName().contains(u"::"))
@@ -157,7 +164,7 @@ QString AbstractMetaBuilderPrivate::fixEnumDefault(const AbstractMetaType &type,
qualified.prepend(resolveEnumValueScopePrefix(metaEnum, token));
qualifiedTokens.append(qualified);
}
- const QString qualifiedExpression = qualifiedTokens.join(u" | "_qs);
+ const QString qualifiedExpression = qualifiedTokens.join(u" | "_s);
if (!typeCast)
return qualifiedExpression;
@@ -175,7 +182,7 @@ bool AbstractMetaBuilder::dontFixDefaultValue(QStringView expr)
|| isIntegerConstant(expr) || isFloatConstant(expr);
}
-QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClass *c,
+QString AbstractMetaBuilderPrivate::qualifyStaticField(const AbstractMetaClassCPtr &c,
QStringView field)
{
if (!c || c->fields().isEmpty())
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
index a64ae68b3..d7aaba5b0 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
@@ -10,25 +10,38 @@
#include "abstractmetalang.h"
#include "abstractmetatype.h"
#include "include.h"
-#include "modifications.h"
#include "typeparser.h"
+#include "modifications_typedefs.h"
+#include "typesystem_typedefs.h"
#include <QtCore/QFileInfo>
#include <QtCore/QList>
#include <QtCore/QMap>
+#include <QtCore/QMultiHash>
#include <QtCore/QSet>
#include <optional>
+#include <set>
class TypeDatabase;
+struct RejectEntry
+{
+ AbstractMetaBuilder::RejectReason reason;
+ QString signature;
+ QString sortkey;
+ QString message;
+};
+
+bool operator<(const RejectEntry &re1, const RejectEntry &re2);
+
class AbstractMetaBuilderPrivate
{
public:
struct TypeClassEntry
{
AbstractMetaType type;
- const AbstractMetaClass *klass;
+ AbstractMetaClassCPtr klass;
};
using TranslateTypeFlags = AbstractMetaBuilder::TranslateTypeFlags;
@@ -36,7 +49,6 @@ public:
Q_DISABLE_COPY(AbstractMetaBuilderPrivate)
AbstractMetaBuilderPrivate();
- ~AbstractMetaBuilderPrivate();
static FileModelItem buildDom(QByteArrayList arguments,
bool addCompilerSupportArguments,
@@ -59,57 +71,66 @@ public:
NamespaceModelItem currentScope() const { return m_scopes.constLast(); }
- AbstractMetaClass *argumentToClass(const ArgumentModelItem &,
- const AbstractMetaClass *currentClass);
+ AbstractMetaClassPtr argumentToClass(const ArgumentModelItem &,
+ const AbstractMetaClassCPtr &currentClass);
- void addAbstractMetaClass(AbstractMetaClass *cls, const _CodeModelItem *item);
- AbstractMetaClass *traverseTypeDef(const FileModelItem &dom,
+ void addAbstractMetaClass(const AbstractMetaClassPtr &cls, const _CodeModelItem *item);
+ AbstractMetaClassPtr traverseTypeDef(const FileModelItem &dom,
const TypeDefModelItem &typeDef,
- AbstractMetaClass *currentClass);
+ const AbstractMetaClassPtr &currentClass);
+ AbstractMetaClassPtr traverseTypeDefHelper(const FileModelItem &dom,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass);
void traverseTypesystemTypedefs();
- AbstractMetaClass *traverseClass(const FileModelItem &dom,
+ AbstractMetaClassPtr traverseClass(const FileModelItem &dom,
const ClassModelItem &item,
- AbstractMetaClass *currentClass);
- void traverseScopeMembers(const ScopeModelItem &item, AbstractMetaClass *metaClass);
+ const AbstractMetaClassPtr &currentClass);
+ void traverseScopeMembers(const ScopeModelItem &item,
+ const AbstractMetaClassPtr &metaClass);
void traverseClassMembers(const ClassModelItem &scopeItem);
- void traverseUsingMembers(AbstractMetaClass *metaClass);
+ void traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const;
void traverseNamespaceMembers(const NamespaceModelItem &scopeItem);
- bool setupInheritance(AbstractMetaClass *metaClass);
- AbstractMetaClass *traverseNamespace(const FileModelItem &dom,
+ bool setupInheritance(const AbstractMetaClassPtr &metaClass);
+ AbstractMetaClassPtr traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &item);
std::optional<AbstractMetaEnum> traverseEnum(const EnumModelItem &item,
- AbstractMetaClass *enclosing,
+ const AbstractMetaClassPtr &enclosing,
const QSet<QString> &enumsDeclarations);
- void traverseEnums(const ScopeModelItem &item, AbstractMetaClass *parent,
+ void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent,
const QStringList &enumsDeclarations);
AbstractMetaFunctionRawPtrList classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
- AbstractMetaClass *currentClass);
- void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent);
+ const AbstractMetaClassPtr &currentClass);
+ void traverseFunctions(const ScopeModelItem& item,
+ const AbstractMetaClassPtr &parent);
static void applyFunctionModifications(AbstractMetaFunction *func);
- void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent);
+ void traverseFields(const ScopeModelItem &item, const AbstractMetaClassPtr &parent);
bool traverseStreamOperator(const FunctionModelItem &functionItem,
- AbstractMetaClass *currentClass);
+ const AbstractMetaClassPtr &currentClass);
void traverseOperatorFunction(const FunctionModelItem &item,
- AbstractMetaClass *currentClass);
+ const AbstractMetaClassPtr &currentClass);
AbstractMetaFunction *traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
QString *errorMessage);
bool traverseAddedGlobalFunction(const AddedFunctionPtr &addedFunc,
QString *errorMessage);
bool traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
QString *errorMessage);
- AbstractMetaFunction *traverseFunction(const FunctionModelItem &function,
- AbstractMetaClass *currentClass);
+ void rejectFunction(const FunctionModelItem &functionItem,
+ const AbstractMetaClassPtr &currentClass,
+ AbstractMetaBuilder::RejectReason reason,
+ const QString &rejectReason);
+ AbstractMetaFunction *traverseFunction(const FunctionModelItem &function,
+ const AbstractMetaClassPtr &currentClass);
std::optional<AbstractMetaField> traverseField(const VariableModelItem &field,
- const AbstractMetaClass *cls);
- void checkFunctionModifications();
+ const AbstractMetaClassCPtr &cls);
+ void checkFunctionModifications() const;
void registerHashFunction(const FunctionModelItem &functionItem,
- AbstractMetaClass *currentClass);
+ const AbstractMetaClassPtr &currentClass);
void registerToStringCapabilityIn(const NamespaceModelItem &namespaceItem);
void registerToStringCapability(const FunctionModelItem &functionItem,
- AbstractMetaClass *currentClass);
+ const AbstractMetaClassPtr &currentClass);
/**
* A conversion operator function should not have its owner class as
@@ -123,48 +144,52 @@ public:
*/
static void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction);
- void parseQ_Properties(AbstractMetaClass *metaClass, const QStringList &declarations);
- void setupEquals(AbstractMetaClass *metaClass);
- void setupComparable(AbstractMetaClass *metaClass);
- void setupExternalConversion(const AbstractMetaClass *cls);
+ void parseQ_Properties(const AbstractMetaClassPtr &metaClass,
+ const QStringList &declarations);
+ void setupEquals(const AbstractMetaClassPtr &metaClass);
+ void setupComparable(const AbstractMetaClassPtr &metaClass);
+ void setupExternalConversion(const AbstractMetaClassCPtr &cls);
static bool isQualifiedCppIdentifier(QStringView e);
QString fixDefaultValue(QString expr, const AbstractMetaType &type,
- const AbstractMetaClass *) const;
+ const AbstractMetaClassCPtr &) const;
QString fixSimpleDefaultValue(QStringView expr,
- const AbstractMetaClass *klass) const;
+ const AbstractMetaClassCPtr &klass) const;
- QString fixEnumDefault(const AbstractMetaType &type, const QString &expr) const;
+ QString fixEnumDefault(const AbstractMetaType &type, const QString &expr,
+ const AbstractMetaClassCPtr &) const;
/// Qualify a static field name for default value expressions
- static QString qualifyStaticField(const AbstractMetaClass *c, QStringView field);
+ static QString qualifyStaticField(const AbstractMetaClassCPtr &c, QStringView field);
std::optional<AbstractMetaType>
- translateType(const TypeInfo &type, const AbstractMetaClass *currentClass,
+ translateType(const TypeInfo &type, const AbstractMetaClassCPtr &currentClass,
TranslateTypeFlags flags = {}, QString *errorMessage = nullptr);
static std::optional<AbstractMetaType>
- translateTypeStatic(const TypeInfo &type, const AbstractMetaClass *current,
+ translateTypeStatic(const TypeInfo &type, const AbstractMetaClassCPtr &current,
AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {},
QString *errorMessageIn = nullptr);
- static TypeEntries findTypeEntriesHelper(const QString &qualifiedName, const QString &name,
- const AbstractMetaClass *currentClass = nullptr,
- AbstractMetaBuilderPrivate *d = nullptr);
- static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name,
- const AbstractMetaClass *currentClass = nullptr,
- AbstractMetaBuilderPrivate *d = nullptr,
- QString *errorMessage = nullptr);
+ static TypeEntryCList findTypeEntriesHelper(const QString &qualifiedName, const QString &name,
+ TranslateTypeFlags flags = {},
+ const AbstractMetaClassCPtr &currentClass = {},
+ AbstractMetaBuilderPrivate *d = nullptr);
+ static TypeEntryCList findTypeEntries(const QString &qualifiedName, const QString &name,
+ TranslateTypeFlags flags = {},
+ const AbstractMetaClassCPtr &currentClass = {},
+ AbstractMetaBuilderPrivate *d = nullptr,
+ QString *errorMessage = nullptr);
qint64 findOutValueFromString(const QString &stringValue, bool &ok);
- AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context,
- TypeInfo *info = Q_NULLPTR,
- ComplexTypeEntry **baseContainerType = Q_NULLPTR) const;
- AbstractMetaClassCList getBaseClasses(const AbstractMetaClass *metaClass) const;
+ AbstractMetaClassPtr findTemplateClass(const QString& name, const AbstractMetaClassCPtr &context,
+ TypeInfo *info = nullptr,
+ ComplexTypeEntryPtr *baseContainerType = nullptr) const;
+ AbstractMetaClassCList getBaseClasses(const AbstractMetaClassCPtr &metaClass) const;
- static bool inheritTemplate(AbstractMetaClass *subclass,
- const AbstractMetaClass *templateClass,
+ static bool inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
const TypeInfo &info);
- static bool inheritTemplate(AbstractMetaClass *subclass,
- const AbstractMetaClass *templateClass,
+ static bool inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags = {});
@@ -175,10 +200,10 @@ public:
static AbstractMetaFunctionPtr
inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass);
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass);
- static void inheritTemplateFunctions(AbstractMetaClass *subclass);
+ static void inheritTemplateFunctions(const AbstractMetaClassPtr &subclass);
static std::optional<AbstractMetaType>
inheritTemplateType(const AbstractMetaTypeList &templateTypes,
const AbstractMetaType &metaType);
@@ -187,31 +212,31 @@ public:
static bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName);
void sortLists();
- void setInclude(TypeEntry *te, const QString &path) const;
+ void setInclude(const TypeEntryPtr &te, const QString &path) const;
static void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods);
- void fillAddedFunctions(AbstractMetaClass *metaClass);
- const AbstractMetaClass *resolveTypeSystemTypeDef(const AbstractMetaType &t) const;
+ void fillAddedFunctions(const AbstractMetaClassPtr &metaClass);
+ AbstractMetaClassCPtr resolveTypeSystemTypeDef(const AbstractMetaType &t) const;
void fixSmartPointers();
- AbstractMetaBuilder *q;
+ AbstractMetaBuilder *q = nullptr;
AbstractMetaClassList m_metaClasses;
AbstractMetaClassList m_templates;
AbstractMetaClassList m_smartPointers;
- QHash<const _CodeModelItem *, AbstractMetaClass *> m_itemToClass;
- QHash<const AbstractMetaClass *, const _CodeModelItem *> m_classToItem;
+ QHash<const _CodeModelItem *, AbstractMetaClassPtr > m_itemToClass;
+ QHash<AbstractMetaClassCPtr, const _CodeModelItem *> m_classToItem;
AbstractMetaFunctionCList m_globalFunctions;
AbstractMetaEnumList m_globalEnums;
- using RejectMap = QMap<QString, AbstractMetaBuilder::RejectReason>;
+ using RejectSet = std::set<RejectEntry>;
- RejectMap m_rejectedClasses;
- RejectMap m_rejectedEnums;
- RejectMap m_rejectedFunctions;
- RejectMap m_rejectedFields;
+ RejectSet m_rejectedClasses;
+ RejectSet m_rejectedEnums;
+ RejectSet m_rejectedFunctions;
+ RejectSet m_rejectedFields;
- QHash<const TypeEntry *, AbstractMetaEnum> m_enums;
+ QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums;
QList<NamespaceModelItem> m_scopes;
@@ -219,6 +244,7 @@ public:
QFileInfoList m_globalHeaders;
QStringList m_headerPaths;
mutable QHash<QString, Include> m_resolveIncludeHash;
+ QMultiHash<QString, QString> m_typedefTargetToName;
QList<TypeClassEntry> m_typeSystemTypeDefs; // look up metatype->class for type system typedefs
ApiExtractorFlags m_apiExtractorFlags;
bool m_skipDeprecated = false;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
index b912273bb..780170c22 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
@@ -11,6 +11,8 @@
#include <QtCore/QDebug>
+#include <algorithm>
+
using namespace Qt::StringLiterals;
class AbstractMetaEnumValueData : public QSharedData
@@ -20,6 +22,7 @@ public:
QString m_stringValue;
EnumValue m_value;
Documentation m_doc;
+ bool m_deprecated = false;
};
AbstractMetaEnumValue::AbstractMetaEnumValue() :
@@ -29,8 +32,8 @@ AbstractMetaEnumValue::AbstractMetaEnumValue() :
AbstractMetaEnumValue::AbstractMetaEnumValue(const AbstractMetaEnumValue &) = default;
AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(const AbstractMetaEnumValue &) = default;
-AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) = default;
-AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) = default;
+AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept = default;
+AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) noexcept = default;
AbstractMetaEnumValue::~AbstractMetaEnumValue() = default;
EnumValue AbstractMetaEnumValue::value() const
@@ -66,6 +69,17 @@ void AbstractMetaEnumValue::setName(const QString &name)
d->m_name = name;
}
+bool AbstractMetaEnumValue::isDeprecated() const
+{
+ return d->m_deprecated;
+}
+
+void AbstractMetaEnumValue::setDeprecated(bool deprecated)
+{
+ if (d->m_deprecated != deprecated)
+ d->m_deprecated = deprecated;
+}
+
Documentation AbstractMetaEnumValue::documentation() const
{
return d->m_doc;
@@ -82,29 +96,67 @@ void AbstractMetaEnumValue::setDocumentation(const Documentation &doc)
class AbstractMetaEnumData : public QSharedData
{
public:
- AbstractMetaEnumData() : m_hasQenumsDeclaration(false), m_signed(true)
+ AbstractMetaEnumData() : m_deprecated(false),
+ m_hasQenumsDeclaration(false), m_signed(true)
{
}
+ int unsignedUsedBits() const;
+ int signedUsedBits() const;
+
AbstractMetaEnumValueList m_enumValues;
- EnumTypeEntry *m_typeEntry = nullptr;
+ EnumTypeEntryCPtr m_typeEntry;
Documentation m_doc;
+ QString m_underlyingType;
EnumKind m_enumKind = CEnum;
Access m_access = Access::Public;
+ uint m_deprecated : 1;
uint m_hasQenumsDeclaration : 1;
uint m_signed : 1;
};
+static int _usedBits(uint64_t v)
+{
+ return (v >> 32) ? 64 : (v >> 16) ? 32 : (v >> 8) ? 16 : 8;
+}
+
+static int _usedBits(int64_t v)
+{
+ return (v >> 31) ? 64 : (v >> 15) ? 32 : (v >> 7) ? 16 : 8;
+}
+
+int AbstractMetaEnumData::unsignedUsedBits() const
+{
+ uint64_t maxValue = 0;
+ for (const auto &v : m_enumValues) {
+ if (const auto uv = v.value().unsignedValue(); uv > maxValue)
+ maxValue = uv;
+ }
+ return _usedBits(maxValue);
+}
+
+int AbstractMetaEnumData::signedUsedBits() const
+{
+ int64_t maxValue = 0;
+ for (const auto &v : m_enumValues) {
+ const auto sv = v.value().value();
+ const auto absV = sv < 0 ? ~sv : sv;
+ if (absV > maxValue)
+ maxValue = absV;
+ }
+ return _usedBits(maxValue);
+}
+
AbstractMetaEnum::AbstractMetaEnum() : d(new AbstractMetaEnumData)
{
}
AbstractMetaEnum::AbstractMetaEnum(const AbstractMetaEnum &) = default;
AbstractMetaEnum &AbstractMetaEnum::operator=(const AbstractMetaEnum&) = default;
-AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) = default;
-AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) = default;
+AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) noexcept = default;
+AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) noexcept = default;
AbstractMetaEnum::~AbstractMetaEnum() = default;
const AbstractMetaEnumValueList &AbstractMetaEnum::values() const
@@ -112,6 +164,16 @@ const AbstractMetaEnumValueList &AbstractMetaEnum::values() const
return d->m_enumValues;
}
+AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const
+{
+ auto te = d->m_typeEntry;
+ AbstractMetaEnumValueList result = d->m_enumValues;
+ auto pred = [te](const AbstractMetaEnumValue &v) {
+ return te->isEnumValueRejected(v.name()); };
+ result.erase(std::remove_if(result.begin(), result.end(), pred), result.end());
+ return result;
+}
+
void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue)
{
d->m_enumValues << enumValue;
@@ -164,6 +226,36 @@ void AbstractMetaEnum::setAccess(Access a)
d->m_access = a;
}
+bool AbstractMetaEnum::isDeprecated() const
+{
+ return d->m_deprecated;
+}
+
+void AbstractMetaEnum::setDeprecated(bool deprecated)
+{
+ if (d->m_deprecated != deprecated)
+ d->m_deprecated = deprecated;
+}
+
+static bool isDeprecatedValue(const AbstractMetaEnumValue &v)
+{
+ return v.isDeprecated();
+};
+
+bool AbstractMetaEnum::hasDeprecatedValues() const
+{
+ return std::any_of(d->m_enumValues.cbegin(), d->m_enumValues.cend(),
+ isDeprecatedValue);
+}
+
+AbstractMetaEnumValueList AbstractMetaEnum::deprecatedValues() const
+{
+ AbstractMetaEnumValueList result;
+ std::copy_if(d->m_enumValues.cbegin(), d->m_enumValues.cend(),
+ std::back_inserter(result), isDeprecatedValue);
+ return result;
+}
+
const Documentation &AbstractMetaEnum::documentation() const
{
return d->m_doc;
@@ -217,12 +309,12 @@ void AbstractMetaEnum::setHasQEnumsDeclaration(bool on)
d->m_hasQenumsDeclaration = on;
}
-EnumTypeEntry *AbstractMetaEnum::typeEntry() const
+EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const
{
return d->m_typeEntry;
}
-void AbstractMetaEnum::setTypeEntry(EnumTypeEntry *entry)
+void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryCPtr &entry)
{
if (d->m_typeEntry != entry)
d->m_typeEntry = entry;
@@ -239,11 +331,39 @@ void AbstractMetaEnum::setSigned(bool s)
d->m_signed = s;
}
+QString AbstractMetaEnum::underlyingType() const
+{
+ return d->m_underlyingType;
+}
+
+void AbstractMetaEnum::setUnderlyingType(const QString &underlyingType)
+{
+ if (d->m_underlyingType != underlyingType)
+ d->m_underlyingType = underlyingType;
+}
+
+int AbstractMetaEnum::usedBits() const
+{
+ return isSigned() ? d->signedUsedBits() : d->unsignedUsedBits();
+}
+
+QString AbstractMetaEnum::intTypeForSize(int usedBits, bool isSigned)
+{
+ QString result = u"int"_s + QString::number(usedBits) + u"_t"_s;
+ return isSigned ? result : u'u' + result;
+}
+
#ifndef QT_NO_DEBUG_STREAM
-static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v)
+static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v, bool forceHex = false)
{
- d << v.name() << '=' << v.value();
+ d << v.name() << '=';
+ if (forceHex)
+ v.value().formatDebugHex(d);
+ else
+ v.value().formatDebug(d);
+ if (v.isDeprecated())
+ d << " (deprecated)";
}
QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v)
@@ -259,15 +379,19 @@ QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v)
static void formatMetaEnum(QDebug &d, const AbstractMetaEnum &e)
{
- d << e.fullName();
+ d << '"' << e.fullName() << '"';
+ if (e.isDeprecated())
+ d << " (deprecated)";
+ d << " \"" << e.underlyingType() << '"';
if (!e.isSigned())
- d << " (unsigned) ";
- d << '[';
+ d << " (unsigned)";
+ d << " [";
const AbstractMetaEnumValueList &values = e.values();
- for (int i = 0, count = values.size(); i < count; ++i) {
+ const bool hasFlags = e.typeEntry()->flags() != nullptr;
+ for (qsizetype i = 0, count = values.size(); i < count; ++i) {
if (i)
- d << ' ';
- formatMetaEnumValue(d, values.at(i));
+ d << ", ";
+ formatMetaEnumValue(d, values.at(i), hasFlags);
}
d << ']';
}
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
index 1151b7164..03d7a3082 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
@@ -7,6 +7,7 @@
#include "abstractmetalang_typedefs.h"
#include "enclosingclassmixin.h"
#include "parser/codemodel_enums.h"
+#include "typesystem_typedefs.h"
#include <QtCore/QSharedDataPointer>
#include <QtCore/QString>
@@ -27,8 +28,8 @@ public:
AbstractMetaEnumValue();
AbstractMetaEnumValue(const AbstractMetaEnumValue &);
AbstractMetaEnumValue &operator=(const AbstractMetaEnumValue &);
- AbstractMetaEnumValue(AbstractMetaEnumValue &&);
- AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&);
+ AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept;
+ AbstractMetaEnumValue &operator=(AbstractMetaEnumValue &&) noexcept;
~AbstractMetaEnumValue();
EnumValue value() const;
@@ -40,9 +41,14 @@ public:
QString name() const;
void setName(const QString &name);
+ bool isDeprecated() const;
+ void setDeprecated(bool deprecated);
+
Documentation documentation() const;
void setDocumentation(const Documentation& doc);
+ int usedBits() const;
+
private:
QSharedDataPointer<AbstractMetaEnumValueData> d;
};
@@ -53,11 +59,12 @@ public:
AbstractMetaEnum();
AbstractMetaEnum(const AbstractMetaEnum &);
AbstractMetaEnum &operator=(const AbstractMetaEnum &);
- AbstractMetaEnum(AbstractMetaEnum &&);
- AbstractMetaEnum &operator=(AbstractMetaEnum &&);
+ AbstractMetaEnum(AbstractMetaEnum &&) noexcept;
+ AbstractMetaEnum &operator=(AbstractMetaEnum &&) noexcept;
~AbstractMetaEnum();
const AbstractMetaEnumValueList &values() const;
+ AbstractMetaEnumValueList nonRejectedValues() const;
void addEnumValue(const AbstractMetaEnumValue &enumValue);
std::optional<AbstractMetaEnumValue> findEnumValue(QStringView value) const;
@@ -70,6 +77,11 @@ public:
bool isPrivate() const { return access() == Access::Private; }
bool isProtected() const { return access() == Access::Protected; }
+ bool isDeprecated() const;
+ void setDeprecated(bool deprecated);
+ bool hasDeprecatedValues() const;
+ AbstractMetaEnumValueList deprecatedValues() const;
+
const Documentation &documentation() const;
void setDocumentation(const Documentation& doc);
@@ -88,12 +100,18 @@ public:
bool hasQEnumsDeclaration() const;
void setHasQEnumsDeclaration(bool on);
- EnumTypeEntry *typeEntry() const;
- void setTypeEntry(EnumTypeEntry *entry);
+ EnumTypeEntryCPtr typeEntry() const;
+ void setTypeEntry(const EnumTypeEntryCPtr &entry);
bool isSigned() const;
void setSigned(bool s);
+ QString underlyingType() const;
+ void setUnderlyingType(const QString &underlyingType);
+
+ static QString intTypeForSize(int usedBits, bool isSigned);
+ int usedBits() const;
+
private:
QSharedDataPointer<AbstractMetaEnumData> d;
};
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
index 8be9ed87d..27a76d04d 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
@@ -36,8 +36,8 @@ AbstractMetaField::AbstractMetaField() : d(new AbstractMetaFieldData)
AbstractMetaField::AbstractMetaField(const AbstractMetaField &) = default;
AbstractMetaField &AbstractMetaField::operator=(const AbstractMetaField &) = default;
-AbstractMetaField::AbstractMetaField(AbstractMetaField &&) = default;
-AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) = default;
+AbstractMetaField::AbstractMetaField(AbstractMetaField &&) noexcept = default;
+AbstractMetaField &AbstractMetaField::operator=(AbstractMetaField &&) noexcept = default;
AbstractMetaField::~AbstractMetaField() = default;
// returned->setEnclosingClass(nullptr);
@@ -56,7 +56,7 @@ std::optional<AbstractMetaField>
/*******************************************************************************
* Indicates that this field has a modification that removes it
*/
-bool AbstractMetaField::isModifiedRemoved(int types) const
+bool AbstractMetaField::isModifiedRemoved() const
{
const FieldModificationList &mods = modifications();
for (const FieldModification &mod : mods) {
@@ -202,7 +202,7 @@ TypeSystem::SnakeCase AbstractMetaField::snakeCase() const
auto typeEntry = enclosingClass()->typeEntry();
const auto snakeCase = typeEntry->snakeCase();
return snakeCase != TypeSystem::SnakeCase::Unspecified
- ? snakeCase : typeEntry->typeSystemTypeEntry()->snakeCase();
+ ? snakeCase : typeSystemTypeEntry(typeEntry)->snakeCase();
}
FieldModificationList AbstractMetaField::modifications() const
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.h b/sources/shiboken6/ApiExtractor/abstractmetafield.h
index 051fca66c..0fa858791 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafield.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetafield.h
@@ -7,6 +7,7 @@
#include "abstractmetalang_typedefs.h"
#include "parser/codemodel_enums.h"
#include "typesystem_enums.h"
+#include "modifications_typedefs.h"
#include "typesystem_typedefs.h"
#include "enclosingclassmixin.h"
@@ -25,13 +26,13 @@ public:
AbstractMetaField();
AbstractMetaField(const AbstractMetaField &);
AbstractMetaField &operator=(const AbstractMetaField &);
- AbstractMetaField(AbstractMetaField &&);
- AbstractMetaField &operator=(AbstractMetaField &&);
+ AbstractMetaField(AbstractMetaField &&) noexcept;
+ AbstractMetaField &operator=(AbstractMetaField &&) noexcept;
~AbstractMetaField();
FieldModificationList modifications() const;
- bool isModifiedRemoved(int types = TypeSystem::All) const;
+ bool isModifiedRemoved() const;
bool generateOpaqueContainer() const;
const AbstractMetaType &type() const;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
index 0ce2d0260..11a02f154 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
@@ -2,21 +2,23 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abstractmetafunction.h"
+#include "abstractmetaargument.h"
#include "abstractmetabuilder.h"
#include "abstractmetalang.h"
#include "abstractmetalang_helpers.h"
#include "abstractmetatype.h"
+#include "addedfunction.h"
#include <codemodel.h>
#include "documentation.h"
#include "exception.h"
#include "messages.h"
#include "codesnip.h"
#include "modifications.h"
-#include "propertyspec.h"
#include "reporthandler.h"
#include "sourcelocation.h"
#include "typedatabase.h"
#include "complextypeentry.h"
+#include "containertypeentry.h"
#include "functiontypeentry.h"
#include "primitivetypeentry.h"
#include "typesystemtypeentry.h"
@@ -26,13 +28,15 @@
#include <QtCore/QDebug>
#include <QtCore/QRegularExpression>
+#include <algorithm>
+
using namespace Qt::StringLiterals;
// Cache FunctionModificationList in a flat list per class (0 for global
// functions, or typically owner/implementing/declaring class.
struct ModificationCacheEntry
{
- const AbstractMetaClass *klass;
+ AbstractMetaClassCPtr klass;
FunctionModificationList modifications;
};
@@ -44,7 +48,6 @@ public:
AbstractMetaFunctionPrivate()
: m_constant(false),
m_reverse(false),
- m_explicit(false),
m_pointerOperator(false),
m_isCallOperator(false)
{
@@ -57,7 +60,7 @@ public:
int overloadNumber(const AbstractMetaFunction *q) const;
const FunctionModificationList &modifications(const AbstractMetaFunction *q,
- const AbstractMetaClass *implementor) const;
+ const AbstractMetaClassCPtr &implementor) const;
bool applyTypeModification(const AbstractMetaFunction *q,
const QString &type, int number, QString *errorMessage);
@@ -68,24 +71,25 @@ public:
mutable QString m_cachedMinimalSignature;
mutable QString m_cachedSignature;
mutable QString m_cachedModifiedName;
+ QString m_unresolvedSignature;
- FunctionTypeEntry* m_typeEntry = nullptr;
+ FunctionTypeEntryPtr m_typeEntry;
AbstractMetaFunction::FunctionType m_functionType = AbstractMetaFunction::NormalFunction;
AbstractMetaType m_type;
QString m_modifiedTypeName;
- const AbstractMetaClass *m_class = nullptr;
- const AbstractMetaClass *m_implementingClass = nullptr;
- const AbstractMetaClass *m_declaringClass = nullptr;
+ AbstractMetaClassCPtr m_class;
+ AbstractMetaClassCPtr m_implementingClass;
+ AbstractMetaClassCPtr m_declaringClass;
mutable ModificationCache m_modificationCache;
int m_propertySpecIndex = -1;
AbstractMetaArgumentList m_arguments;
AddedFunctionPtr m_addedFunction;
SourceLocation m_sourceLocation;
AbstractMetaFunction::Attributes m_attributes;
+ FunctionAttributes m_cppAttributes;
AbstractMetaFunction::Flags m_flags;
uint m_constant : 1;
uint m_reverse : 1;
- uint m_explicit : 1;
uint m_pointerOperator : 1;
uint m_isCallOperator : 1;
mutable int m_cachedOverloadNumber = TypeSystem::OverloadNumberUnset;
@@ -115,9 +119,9 @@ AbstractMetaFunction::AbstractMetaFunction(const AddedFunctionPtr &addedFunc) :
setAccess(Access::Public);
break;
}
- AbstractMetaFunction::Attributes atts = AbstractMetaFunction::FinalInTargetLang;
+ AbstractMetaFunction::Attributes atts;
if (addedFunc->isStatic())
- atts |= AbstractMetaFunction::Static;
+ setCppAttribute(FunctionAttribute::Static);
if (addedFunc->isClassMethod())
atts |= AbstractMetaFunction::ClassMethod;
setAttributes(atts);
@@ -210,20 +214,19 @@ void AbstractMetaFunction::setPointerOperator(bool value)
bool AbstractMetaFunction::isExplicit() const
{
- return d->m_explicit;
+ return d->m_cppAttributes.testFlag(FunctionAttribute::Explicit);
}
void AbstractMetaFunction::setExplicit(bool isExplicit)
{
- d->m_explicit = isExplicit;
+ d->m_cppAttributes.setFlag(FunctionAttribute::Explicit, isExplicit);
}
bool AbstractMetaFunction::returnsBool() const
{
if (d->m_type.typeUsagePattern() != AbstractMetaType::PrimitivePattern)
return false;
- const auto *pte = d->m_type.typeEntry()->asPrimitive();
- return pte->basicReferencedTypeEntry()->name() == u"bool";
+ return basicReferencedTypeEntry(d->m_type.typeEntry())->name() == u"bool";
}
bool AbstractMetaFunction::isOperatorBool() const
@@ -258,6 +261,21 @@ void AbstractMetaFunction::operator-=(AbstractMetaFunction::Attribute attribute)
d->m_attributes.setFlag(attribute, false);
}
+FunctionAttributes AbstractMetaFunction::cppAttributes() const
+{
+ return d->m_cppAttributes;
+}
+
+void AbstractMetaFunction::setCppAttributes(FunctionAttributes a)
+{
+ d->m_cppAttributes = a;
+}
+
+void AbstractMetaFunction::setCppAttribute(FunctionAttribute a, bool on)
+{
+ d->m_cppAttributes.setFlag(a, on);
+}
+
AbstractMetaFunction::Flags AbstractMetaFunction::flags() const
{
return d->m_flags;
@@ -271,9 +289,9 @@ void AbstractMetaFunction::setFlags(Flags f)
/*******************************************************************************
* Indicates that this function has a modification that removes it
*/
-bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const
+bool AbstractMetaFunction::isModifiedRemoved(AbstractMetaClassCPtr cls) const
{
- if (!isInGlobalScope() && cls == nullptr)
+ if (!isInGlobalScope() && !cls)
cls = d->m_implementingClass;
for (const auto &mod : modifications(cls)) {
if (mod.isRemoved())
@@ -283,6 +301,17 @@ bool AbstractMetaFunction::isModifiedRemoved(const AbstractMetaClass *cls) const
return false;
}
+bool AbstractMetaFunction::isModifiedFinal(AbstractMetaClassCPtr cls) const
+{
+ if (!isInGlobalScope() && cls == nullptr)
+ cls = d->m_implementingClass;
+ for (const auto &mod : modifications(cls)) {
+ if (mod.modifiers().testFlag(FunctionModification::Final))
+ return true;
+ }
+ return false;
+}
+
bool AbstractMetaFunction::isVoid() const
{
return d->m_type.isVoid();
@@ -298,12 +327,12 @@ void AbstractMetaFunction::setType(const AbstractMetaType &type)
d->m_type = type;
}
-const AbstractMetaClass *AbstractMetaFunction::ownerClass() const
+AbstractMetaClassCPtr AbstractMetaFunction::ownerClass() const
{
return d->m_class;
}
-void AbstractMetaFunction::setOwnerClass(const AbstractMetaClass *cls)
+void AbstractMetaFunction::setOwnerClass(const AbstractMetaClassCPtr &cls)
{
d->m_class = cls;
}
@@ -327,7 +356,7 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra
result |= EqualImplementor;
// Attributes
- if (attributes() == other->attributes())
+ if (attributes() == other->attributes() && cppAttributes() == other->cppAttributes())
result |= EqualAttributes;
// Compare types
@@ -358,10 +387,10 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra
maxArguments = arguments();
}
- int minCount = minArguments.size();
- int maxCount = maxArguments.size();
+ const auto minCount = minArguments.size();
+ const auto maxCount = maxArguments.size();
bool same = true;
- for (int i = 0; i < maxCount; ++i) {
+ for (qsizetype i = 0; i < maxCount; ++i) {
if (i < minCount) {
const AbstractMetaArgument &min_arg = minArguments.at(i);
const AbstractMetaArgument &max_arg = maxArguments.at(i);
@@ -412,6 +441,10 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const
{
auto *cpy = new AbstractMetaFunction;
cpy->setAttributes(attributes());
+ auto ca = cppAttributes();
+ // Historical bug: explicit was not copied! (causing nontypetemplate_test.py fail)
+ ca.setFlag(FunctionAttribute::Explicit, false);
+ cpy->setCppAttributes(ca);
cpy->setFlags(flags());
cpy->setAccess(access());
cpy->setName(name());
@@ -449,6 +482,9 @@ bool AbstractMetaFunction::generateBinding() const
{
switch (d->m_functionType) {
case ConversionOperator:
+ if (d->m_name != u"operator int" && d->m_name != u"operator double")
+ return false;
+ break;
case AssignmentOperatorFunction:
case MoveAssignmentOperatorFunction:
case AbstractMetaFunction::MoveConstructorFunction:
@@ -458,9 +494,19 @@ bool AbstractMetaFunction::generateBinding() const
return false;
break;
}
+ // Can we access the wrapper in case of a protected method? If not,
+ // disable for consistency regardless of avoidProtectedHack.
+ if (isProtected()) {
+ const auto typeFlags = ownerClass()->typeEntry()->typeFlags();
+ if (typeFlags.testFlag(ComplexTypeEntry::DisableWrapper))
+ return false;
+ }
if (isPrivate() && d->m_functionType != EmptyFunction)
return false;
- return d->m_name != u"qt_metacall" && !usesRValueReferences()
+ // RValue references only for user-specified
+ // functions (<add-function>/<declare-function>/<function>)
+ return d->m_name != u"qt_metacall" &&
+ (!usesRValueReferences() || d->m_addedFunction || d->m_typeEntry)
&& !isModifiedRemoved();
}
@@ -470,7 +516,7 @@ bool AbstractMetaFunction::isWhiteListed() const
case NormalFunction:
case SignalFunction:
case SlotFunction:
- if (auto *dc = declaringClass()) {
+ if (auto dc = declaringClass()) {
const QSet<QString> &whiteList = dc->typeEntry()->generateFunctions();
return whiteList.isEmpty() || whiteList.contains(d->m_name)
|| whiteList.contains(minimalSignature());
@@ -521,6 +567,16 @@ QString AbstractMetaFunction::classQualifiedSignature() const
return result;
}
+QString AbstractMetaFunction::unresolvedSignature() const
+{
+ return d->m_unresolvedSignature;
+}
+
+void AbstractMetaFunction::setUnresolvedSignature(const QString &s)
+{
+ d->m_unresolvedSignature = s;
+}
+
bool AbstractMetaFunction::isConstant() const
{
return d->m_constant;
@@ -533,18 +589,23 @@ void AbstractMetaFunction::setConstant(bool constant)
bool AbstractMetaFunction::isUserAdded() const
{
- return !d->m_addedFunction.isNull() && !d->m_addedFunction->isDeclaration();
+ return d->m_addedFunction && !d->m_addedFunction->isDeclaration();
+}
+
+bool AbstractMetaFunction::isUserAddedPythonOverride() const
+{
+ return d->m_addedFunction && d->m_addedFunction->isPythonOverride();
}
bool AbstractMetaFunction::isUserDeclared() const
{
- return !d->m_addedFunction.isNull() && d->m_addedFunction->isDeclaration();
+ return d->m_addedFunction && d->m_addedFunction->isDeclaration();
}
int AbstractMetaFunction::actualMinimumArgumentCount() const
{
int count = 0;
- for (int i = 0, size = d->m_arguments.size(); i < size; ++i && ++count) {
+ for (qsizetype i = 0, size = d->m_arguments.size(); i < size; ++i && ++count) {
const auto &arg = d->m_arguments.at(i);
if (arg.isModifiedRemoved())
--count;
@@ -568,7 +629,7 @@ int AbstractMetaFunction::actualArgumentIndex(int index) const
}
// Returns reference counts for argument at idx, or all arguments if idx == -2
-QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
+QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClassCPtr &cls, int idx) const
{
QList<ReferenceCount> returned;
@@ -583,7 +644,7 @@ QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaCl
return returned;
}
-ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const
+ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const
{
for (const auto &mod : modifications(cls)) {
for (const ArgumentModification &argumentMod : mod.argument_mods()) {
@@ -632,28 +693,28 @@ bool AbstractMetaFunction::argumentRemoved(int key) const
return false;
}
-const AbstractMetaClass *AbstractMetaFunction::targetLangOwner() const
+AbstractMetaClassCPtr AbstractMetaFunction::targetLangOwner() const
{
return d->m_class && d->m_class->isInvisibleNamespace()
? d->m_class->targetLangEnclosingClass() : d->m_class;
}
-const AbstractMetaClass *AbstractMetaFunction::declaringClass() const
+AbstractMetaClassCPtr AbstractMetaFunction::declaringClass() const
{
return d->m_declaringClass;
}
-void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClass *cls)
+void AbstractMetaFunction::setDeclaringClass(const AbstractMetaClassCPtr &cls)
{
d->m_declaringClass = cls;
}
-const AbstractMetaClass *AbstractMetaFunction::implementingClass() const
+AbstractMetaClassCPtr AbstractMetaFunction::implementingClass() const
{
return d->m_implementingClass;
}
-void AbstractMetaFunction::setImplementingClass(const AbstractMetaClass *cls)
+void AbstractMetaFunction::setImplementingClass(const AbstractMetaClassCPtr &cls)
{
d->m_implementingClass = cls;
}
@@ -678,15 +739,23 @@ void AbstractMetaFunction::addArgument(const AbstractMetaArgument &argument)
d->m_arguments << argument;
}
+static bool modifiedDeprecated(const FunctionModification &mod)
+{
+ return mod.modifiers().testFlag(FunctionModification::Deprecated);
+}
+
+static bool modifiedUndeprecated(const FunctionModification &mod)
+{
+ return mod.modifiers().testFlag(FunctionModification::Undeprecated);
+}
+
bool AbstractMetaFunction::isDeprecated() const
{
- if (d->m_attributes.testFlag(Attribute::Deprecated))
- return true;
- for (const auto &modification : modifications(declaringClass())) {
- if (modification.isDeprecated())
- return true;
- }
- return false;
+ const auto &mods = modifications(declaringClass());
+
+ return d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated)
+ ? std::none_of(mods.cbegin(), mods.cend(), modifiedUndeprecated)
+ : std::any_of(mods.cbegin(), mods.cend(), modifiedDeprecated);
}
bool AbstractMetaFunction::isConstructor() const
@@ -777,12 +846,12 @@ void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocatio
d->m_sourceLocation = sourceLocation;
}
-static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass)
+static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClassCPtr &klass)
{
return klass->typeEntry()->allowThread();
}
-static inline bool hasAllowThreadMod(const AbstractMetaClass *klass)
+static inline bool hasAllowThreadMod(const AbstractMetaClassCPtr &klass)
{
return allowThreadMod(klass) != TypeSystem::AllowThread::Unspecified;
}
@@ -815,7 +884,7 @@ bool AbstractMetaFunction::allowThread() const
return result;
}
-TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const
+TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const
{
for (const auto &modification : modifications(cls)) {
for (const ArgumentModification &argumentModification : modification.argument_mods()) {
@@ -834,10 +903,15 @@ const QString &AbstractMetaFunction::modifiedTypeName() const
bool AbstractMetaFunction::generateOpaqueContainerReturn() const
{
- return isTypeModified()
- && d->m_type.typeUsagePattern() == AbstractMetaType::ContainerPattern
- && d->m_type.referenceType() == LValueReference
- && d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName);
+ if (!isTypeModified() || d->m_type.typeUsagePattern() != AbstractMetaType::ContainerPattern)
+ return false;
+ // Needs to be a reference to a container, allow by value only for spans
+ if (d->m_type.referenceType() != LValueReference) {
+ auto cte = std::static_pointer_cast<const ContainerTypeEntry>(d->m_type.typeEntry());
+ if (cte->containerKind() != ContainerTypeEntry::SpanContainer)
+ return false;
+ }
+ return d->m_type.generateOpaqueContainerForGetter(d->m_modifiedTypeName);
}
bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const
@@ -925,12 +999,14 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu
{
QString result = m_originalName + u'(';
for (qsizetype i = 0; i < m_arguments.size(); ++i) {
+ const auto &argument = m_arguments.at(i);
if (i > 0)
result += u',';
- result += comment
- ? m_arguments.at(i).modifiedType().minimalSignature()
- : m_arguments.at(i).type().minimalSignature();
+ const auto &type = comment ? argument.modifiedType() : argument.type();
+ result += type.minimalSignature();
+ if (comment && argument.hasDefaultValueExpression())
+ result += u'=';
}
result += u')';
if (m_constant)
@@ -952,6 +1028,14 @@ QString AbstractMetaFunction::minimalSignature() const
return d->m_cachedMinimalSignature;
}
+QStringList AbstractMetaFunction::modificationSignatures() const
+{
+ QStringList result{minimalSignature()};
+ if (d->m_unresolvedSignature != result.constFirst())
+ result.append(d->m_unresolvedSignature);
+ return result;
+}
+
QString AbstractMetaFunction::signatureComment() const
{
return d->formatMinimalSignature(this, true);
@@ -960,9 +1044,10 @@ QString AbstractMetaFunction::signatureComment() const
QString AbstractMetaFunction::debugSignature() const
{
QString result;
- const bool isOverride = attributes() & AbstractMetaFunction::OverriddenCppMethod;
- const bool isFinal = attributes() & AbstractMetaFunction::FinalCppMethod;
- if (!isOverride && !isFinal && (attributes() & AbstractMetaFunction::VirtualCppMethod))
+ const auto attributes = cppAttributes();
+ const bool isOverride = attributes.testFlag(FunctionAttribute::Override);
+ const bool isFinal = attributes.testFlag(FunctionAttribute::Final);
+ if (!isOverride && !isFinal && (attributes.testFlag(FunctionAttribute::Virtual)))
result += u"virtual "_s;
if (d->m_implementingClass)
result += d->m_implementingClass->qualifiedCppName() + u"::"_s;
@@ -975,12 +1060,12 @@ QString AbstractMetaFunction::debugSignature() const
}
FunctionModificationList AbstractMetaFunction::findClassModifications(const AbstractMetaFunction *f,
- const AbstractMetaClass *implementor)
+ AbstractMetaClassCPtr implementor)
{
- const QString signature = f->minimalSignature();
+ const auto signatures = f->modificationSignatures();
FunctionModificationList mods;
while (implementor) {
- mods += implementor->typeEntry()->functionModifications(signature);
+ mods += implementor->typeEntry()->functionModifications(signatures);
if ((implementor == implementor->baseClass()) ||
(implementor == f->implementingClass() && !mods.isEmpty())) {
break;
@@ -992,15 +1077,16 @@ FunctionModificationList AbstractMetaFunction::findClassModifications(const Abst
FunctionModificationList AbstractMetaFunction::findGlobalModifications(const AbstractMetaFunction *f)
{
- return TypeDatabase::instance()->functionModifications(f->minimalSignature());
+ auto *td = TypeDatabase::instance();
+ return td->globalFunctionModifications(f->modificationSignatures());
}
const FunctionModificationList &
AbstractMetaFunctionPrivate::modifications(const AbstractMetaFunction *q,
- const AbstractMetaClass *implementor) const
+ const AbstractMetaClassCPtr &implementor) const
{
- if (!m_addedFunction.isNull())
- return m_addedFunction->modifications;
+ if (m_addedFunction)
+ return m_addedFunction->modifications();
for (const auto &ce : m_modificationCache) {
if (ce.klass == implementor)
return ce.modifications;
@@ -1014,9 +1100,9 @@ const FunctionModificationList &
}
const FunctionModificationList &
- AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const
+ AbstractMetaFunction::modifications(AbstractMetaClassCPtr implementor) const
{
- if (implementor == nullptr)
+ if (!implementor)
implementor = d->m_class;
return d->modifications(this, implementor);
}
@@ -1026,9 +1112,15 @@ void AbstractMetaFunction::clearModificationsCache()
d->m_modificationCache.clear();
}
+const DocModificationList AbstractMetaFunction::addedFunctionDocModifications() const
+{
+ return d->m_addedFunction
+ ? d->m_addedFunction->docModifications() : DocModificationList{};
+}
+
QString AbstractMetaFunction::argumentName(int index,
bool /* create */,
- const AbstractMetaClass * /* implementor */) const
+ AbstractMetaClassCPtr /* implementor */) const
{
return d->m_arguments[--index].name();
}
@@ -1043,16 +1135,27 @@ void AbstractMetaFunction::setPropertySpecIndex(int i)
d->m_propertySpecIndex = i;
}
-FunctionTypeEntry *AbstractMetaFunction::typeEntry() const
+FunctionTypeEntryPtr AbstractMetaFunction::typeEntry() const
{
return d->m_typeEntry;
}
-void AbstractMetaFunction::setTypeEntry(FunctionTypeEntry *typeEntry)
+void AbstractMetaFunction::setTypeEntry(const FunctionTypeEntryPtr &typeEntry)
{
d->m_typeEntry = typeEntry;
}
+QString AbstractMetaFunction::targetLangPackage() const
+{
+ if (d->m_addedFunction != nullptr)
+ return d->m_addedFunction->targetLangPackage();
+ if (d->m_class != nullptr)
+ return d->m_class->typeEntry()->targetLangPackage();
+ if (d->m_typeEntry != nullptr)
+ return d->m_typeEntry->targetLangPackage();
+ return {};
+}
+
bool AbstractMetaFunction::isCallOperator() const
{
return d->m_name == u"operator()";
@@ -1149,12 +1252,12 @@ void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e)
d->m_exceptionSpecification = e;
}
-static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClass *klass)
+static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClassCPtr &klass)
{
return klass->typeEntry()->exceptionHandling();
}
-static inline bool hasExceptionMod(const AbstractMetaClass *klass)
+static inline bool hasExceptionMod(const AbstractMetaClassCPtr &klass)
{
return exceptionMod(klass) != TypeSystem::ExceptionHandling::Unspecified;
}
@@ -1308,7 +1411,7 @@ bool AbstractMetaFunction::isInplaceOperator() const
bool AbstractMetaFunction::isVirtual() const
{
- return d->m_attributes.testFlag(AbstractMetaFunction::VirtualCppMethod);
+ return d->m_cppAttributes.testFlag(FunctionAttribute::Virtual);
}
QString AbstractMetaFunctionPrivate::modifiedName(const AbstractMetaFunction *q) const
@@ -1333,7 +1436,7 @@ QString AbstractMetaFunction::modifiedName() const
AbstractMetaFunctionCPtr
AbstractMetaFunction::find(const AbstractMetaFunctionCList &haystack,
- QStringView needle)
+ QAnyStringView needle)
{
for (const auto &f : haystack) {
if (f->name() == needle)
@@ -1431,17 +1534,14 @@ TypeSystem::SnakeCase AbstractMetaFunction::snakeCase() const
return mod.snakeCase();
}
- if (d->m_typeEntry) { // Global function
- const auto snakeCase = d->m_typeEntry->snakeCase();
- return snakeCase != TypeSystem::SnakeCase::Unspecified
- ? snakeCase : d->m_typeEntry->typeSystemTypeEntry()->snakeCase();
- }
+ if (d->m_typeEntry) // Global function
+ return typeSystemTypeEntry(d->m_typeEntry)->snakeCase();
if (d->m_class) {
auto typeEntry = d->m_class->typeEntry();
const auto snakeCase = typeEntry->snakeCase();
return snakeCase != TypeSystem::SnakeCase::Unspecified
- ? snakeCase : typeEntry->typeSystemTypeEntry()->snakeCase();
+ ? snakeCase : typeSystemTypeEntry(typeEntry)->snakeCase();
}
return TypeSystem::SnakeCase::Disabled;
}
@@ -1455,7 +1555,7 @@ bool AbstractMetaFunction::injectedCodeUsesPySelf() const
bool AbstractMetaFunction::injectedCodeCallsPythonOverride() const
{
static const QRegularExpression
- overrideCallRegexCheck(QStringLiteral(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)"));
+ overrideCallRegexCheck(R"(PyObject_Call\s*\(\s*%PYTHON_METHOD_OVERRIDE\s*,)"_L1);
Q_ASSERT(overrideCallRegexCheck.isValid());
return injectedCodeContains(overrideCallRegexCheck, TypeSystem::CodeSnipPositionAny,
TypeSystem::NativeCode);
@@ -1465,13 +1565,13 @@ bool AbstractMetaFunction::injectedCodeHasReturnValueAttribution(TypeSystem::Lan
{
if (language == TypeSystem::TargetLangCode) {
static const QRegularExpression
- retValAttributionRegexCheck_target(QStringLiteral(R"(%PYARG_0\s*=[^=]\s*.+)"));
+ retValAttributionRegexCheck_target(R"(%PYARG_0\s*=[^=]\s*.+)"_L1);
Q_ASSERT(retValAttributionRegexCheck_target.isValid());
return injectedCodeContains(retValAttributionRegexCheck_target, TypeSystem::CodeSnipPositionAny, language);
}
static const QRegularExpression
- retValAttributionRegexCheck_native(QStringLiteral(R"(%0\s*=[^=]\s*.+)"));
+ retValAttributionRegexCheck_native(R"(%0\s*=[^=]\s*.+)"_L1);
Q_ASSERT(retValAttributionRegexCheck_native.isValid());
return injectedCodeContains(retValAttributionRegexCheck_native, TypeSystem::CodeSnipPositionAny, language);
}
@@ -1552,12 +1652,15 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &debug) const
if (d->m_exceptionHandlingModification != TypeSystem::ExceptionHandling::Unspecified)
debug << " exeption-mod " << int(d->m_exceptionHandlingModification);
debug << '(';
- for (int i = 0, count = d->m_arguments.size(); i < count; ++i) {
+ for (qsizetype i = 0, count = d->m_arguments.size(); i < count; ++i) {
if (i)
debug << ", ";
debug << d->m_arguments.at(i);
}
- debug << "), signature=\"" << minimalSignature() << '"';
+ const QString signature = minimalSignature();
+ debug << "), signature=\"" << signature << '"';
+ if (signature != d->m_unresolvedSignature)
+ debug << ", unresolvedSignature=\"" << d->m_unresolvedSignature << '"';
if (d->m_constant)
debug << " [const]";
if (d->m_reverse)
@@ -1566,9 +1669,9 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &debug) const
debug << " [userAdded]";
if (isUserDeclared())
debug << " [userDeclared]";
- if (d->m_explicit)
+ if (d->m_cppAttributes.testFlag(FunctionAttribute::Explicit))
debug << " [explicit]";
- if (attributes().testFlag(AbstractMetaFunction::Deprecated))
+ if (d->m_cppAttributes.testFlag(FunctionAttribute::Deprecated))
debug << " [deprecated]";
if (d->m_pointerOperator)
debug << " [operator->]";
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
index 4c0815540..e252e439d 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
@@ -6,10 +6,12 @@
#include "abstractmetalang_enums.h"
#include "abstractmetalang_typedefs.h"
-#include "abstractmetaargument.h"
#include "typesystem_enums.h"
+#include "modifications_typedefs.h"
#include "typesystem_typedefs.h"
+#include "parser/codemodel_enums.h"
+#include <QtCore/QMetaObject>
#include <QtCore/QScopedPointer>
#include <optional>
@@ -30,6 +32,8 @@ class AbstractMetaFunction
{
Q_GADGET
public:
+ Q_DISABLE_COPY_MOVE(AbstractMetaFunction)
+
enum FunctionType {
ConstructorFunction,
CopyConstructorFunction,
@@ -88,29 +92,18 @@ public:
enum Attribute {
None = 0x00000000,
- Friendly = 0x00000001,
-
- Abstract = 0x00000002,
- Static = 0x00000004,
ClassMethod = 0x00000008,
- FinalInTargetLang = 0x00000010,
-
GetterFunction = 0x00000020,
SetterFunction = 0x00000040,
PropertyReader = 0x00000100,
PropertyWriter = 0x00000200,
PropertyResetter = 0x00000400,
+ PropertyNotify = 0x00000800,
- Invokable = 0x00001000,
-
- VirtualCppMethod = 0x00010000,
- OverriddenCppMethod = 0x00020000,
- FinalCppMethod = 0x00040000,
// Add by meta builder (implicit constructors, inherited methods, etc)
AddedMethod = 0x001000000,
- Deprecated = 0x002000000 // Code annotation
};
Q_DECLARE_FLAGS(Attributes, Attribute)
Q_FLAG(Attribute)
@@ -121,24 +114,27 @@ public:
void operator+=(Attribute attribute);
void operator-=(Attribute attribute);
+ FunctionAttributes cppAttributes() const;
+ void setCppAttributes(FunctionAttributes a);
+ void setCppAttribute(FunctionAttribute a, bool on = true);
+
enum class Flag { // Internal flags not relevant for comparing functions
// Binary operator whose leading/trailing argument was removed by metabuilder
OperatorLeadingClassArgumentRemoved = 0x1,
OperatorTrailingClassArgumentRemoved = 0x2,
OperatorClassArgumentByValue = 0x4, // The removed class argument was passed by value
InheritedFromTemplate = 0x8, // Inherited from a template in metabuilder
- HiddenFriend = 0x10
+ HiddenFriend = 0x10,
+ PrivateSignal = 0x20 // Private Qt signal (cannot emit from client code)
};
Q_DECLARE_FLAGS(Flags, Flag)
Flags flags() const;
void setFlags(Flags f);
- bool isFinalInTargetLang() const;
bool isAbstract() const;
bool isClassMethod() const;
bool isStatic() const;
- bool isInvokable() const;
bool isPropertyReader() const;
bool isPropertyWriter() const;
bool isPropertyResetter() const;
@@ -231,12 +227,15 @@ public:
QString modifiedName() const;
QString minimalSignature() const;
+ /// List of signatures matched for modifications
+ QStringList modificationSignatures() const;
// Signature with replaced argument types and return type for overload
// decisor comment.
QString signatureComment() const;
QString debugSignature() const; // including virtual/override/final, etc., for debugging only.
- bool isModifiedRemoved(const AbstractMetaClass *cls = nullptr) const;
+ bool isModifiedRemoved(AbstractMetaClassCPtr cls = {}) const;
+ bool isModifiedFinal(AbstractMetaClassCPtr cls = {}) const;
bool isVoid() const;
@@ -244,19 +243,19 @@ public:
void setType(const AbstractMetaType &type);
// The class that has this function as a member.
- const AbstractMetaClass *ownerClass() const;
- void setOwnerClass(const AbstractMetaClass *cls);
+ AbstractMetaClassCPtr ownerClass() const;
+ void setOwnerClass(const AbstractMetaClassCPtr &cls);
// Owner excluding invisible namespaces
- const AbstractMetaClass *targetLangOwner() const;
+ AbstractMetaClassCPtr targetLangOwner() const;
// The first class in a hierarchy that declares the function
- const AbstractMetaClass *declaringClass() const;
- void setDeclaringClass(const AbstractMetaClass *cls);
+ AbstractMetaClassCPtr declaringClass() const;
+ void setDeclaringClass(const AbstractMetaClassCPtr &cls);
// The class that actually implements this function
- const AbstractMetaClass *implementingClass() const;
- void setImplementingClass(const AbstractMetaClass *cls);
+ AbstractMetaClassCPtr implementingClass() const;
+ void setImplementingClass(const AbstractMetaClassCPtr &cls);
const AbstractMetaArgumentList &arguments() const;
AbstractMetaArgumentList &arguments();
@@ -292,11 +291,16 @@ public:
/// Return a signature qualified by class name, for error reporting.
QString classQualifiedSignature() const;
+ /// Signature with unresolved typedefs as seen by the code parser
+ QString unresolvedSignature() const;
+ void setUnresolvedSignature(const QString &);
+
bool isConstant() const;
void setConstant(bool constant);
/// Returns true if the AbstractMetaFunction was added by the user via the type system description.
bool isUserAdded() const;
+ bool isUserAddedPythonOverride() const;
/// Returns true if the AbstractMetaFunction was declared by the user via
/// the type system description.
bool isUserDeclared() const;
@@ -310,11 +314,13 @@ public:
QString conversionRule(TypeSystem::Language language, int idx) const;
bool hasConversionRule(TypeSystem::Language language, int idx) const;
- QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const;
- ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const;
+ QList<ReferenceCount>
+ referenceCounts(const AbstractMetaClassCPtr &cls, int idx = -2) const;
+ ArgumentOwner argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const;
// Returns the ownership rules for the given argument (target lang).
- TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const;
+ TypeSystem::Ownership
+ argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const;
const QString &modifiedTypeName() const;
bool isTypeModified() const { return !modifiedTypeName().isEmpty(); }
@@ -354,29 +360,32 @@ public:
*/
bool hasSignatureModifications() const;
- const FunctionModificationList &modifications(const AbstractMetaClass *implementor = nullptr) const;
+ const FunctionModificationList &modifications(AbstractMetaClassCPtr implementor = {}) const;
void clearModificationsCache();
+ const DocModificationList addedFunctionDocModifications() const;
+
static FunctionModificationList findClassModifications(const AbstractMetaFunction *f,
- const AbstractMetaClass *implementor);
+ AbstractMetaClassCPtr implementor);
static FunctionModificationList findGlobalModifications(const AbstractMetaFunction *f);
/**
* Return the argument name if there is a modification the renamed value will be returned
*/
- QString argumentName(int index, bool create = true, const AbstractMetaClass *cl = nullptr) const;
+ QString argumentName(int index, bool create = true, AbstractMetaClassCPtr cl = {}) const;
int propertySpecIndex() const;
void setPropertySpecIndex(int i);
- FunctionTypeEntry* typeEntry() const;
+ FunctionTypeEntryPtr typeEntry() const;
+ void setTypeEntry(const FunctionTypeEntryPtr &typeEntry);
- void setTypeEntry(FunctionTypeEntry* typeEntry);
+ QString targetLangPackage() const;
bool isCallOperator() const;
static AbstractMetaFunctionCPtr
- find(const AbstractMetaFunctionCList &haystack, QStringView needle);
+ find(const AbstractMetaFunctionCList &haystack, QAnyStringView needle);
bool matches(OperatorQueryOptions) const;
@@ -435,19 +444,14 @@ private:
QScopedPointer<AbstractMetaFunctionPrivate> d;
};
-inline bool AbstractMetaFunction::isFinalInTargetLang() const
-{
- return attributes().testFlag(FinalInTargetLang);
-}
-
inline bool AbstractMetaFunction::isAbstract() const
{
- return attributes().testFlag(Abstract);
+ return cppAttributes().testFlag(FunctionAttribute::Abstract);
}
inline bool AbstractMetaFunction::isStatic() const
{
- return attributes().testFlag(Static);
+ return cppAttributes().testFlag(FunctionAttribute::Static);
}
inline bool AbstractMetaFunction::isClassMethod() const
@@ -455,11 +459,6 @@ inline bool AbstractMetaFunction::isClassMethod() const
return attributes().testFlag(ClassMethod);
}
-inline bool AbstractMetaFunction::isInvokable() const
-{
- return attributes().testFlag(Invokable);
-}
-
inline bool AbstractMetaFunction::isPropertyReader() const
{
return attributes().testFlag(PropertyReader);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
index 33ed659c0..fb49cc9d0 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
@@ -2,10 +2,14 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abstractmetalang.h"
+#include "anystringview_helpers.h"
#include "abstractmetalang_helpers.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
#include "abstractmetafunction.h"
+#include "abstractmetatype.h"
#include "abstractmetafield.h"
+#include "parser/codemodel.h"
#include "documentation.h"
#include "messages.h"
#include "modifications.h"
@@ -53,24 +57,23 @@ public:
{
}
- ~AbstractMetaClassPrivate()
- {
- qDeleteAll(m_templateArgs);
- }
-
void addFunction(const AbstractMetaFunctionCPtr &function);
static AbstractMetaFunction *
createFunction(const QString &name, AbstractMetaFunction::FunctionType t,
Access access, const AbstractMetaArgumentList &arguments,
- const AbstractMetaType &returnType, AbstractMetaClass *q);
+ const AbstractMetaType &returnType, const AbstractMetaClassPtr &q);
void addConstructor(AbstractMetaFunction::FunctionType t,
Access access,
const AbstractMetaArgumentList &arguments,
- AbstractMetaClass *q);
- void addUsingConstructors(AbstractMetaClass *q);
- bool isUsingMember(const AbstractMetaClass *c, const QString &memberName,
+ const AbstractMetaClassPtr &q);
+ void addUsingConstructors(const AbstractMetaClassPtr &q);
+ void sortFunctions();
+ void setFunctions(const AbstractMetaFunctionCList &functions,
+ const AbstractMetaClassCPtr &q);
+ bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName,
Access minimumAccess) const;
bool hasConstructors() const;
+ qsizetype indexOfProperty(const QString &name) const;
uint m_hasVirtuals : 1;
uint m_isPolymorphic : 1;
@@ -91,14 +94,15 @@ public:
Documentation m_doc;
- const AbstractMetaClass *m_enclosingClass = nullptr;
- const AbstractMetaClass *m_defaultSuperclass = nullptr;
+ AbstractMetaClassCPtr m_enclosingClass;
+ AbstractMetaClassCPtr m_defaultSuperclass;
AbstractMetaClassCList m_baseClasses; // Real base classes after setting up inheritance
AbstractMetaTypeList m_baseTemplateInstantiations;
- const AbstractMetaClass *m_extendedNamespace = nullptr;
+ AbstractMetaClassCPtr m_extendedNamespace;
- const AbstractMetaClass *m_templateBaseClass = nullptr;
+ AbstractMetaClassCPtr m_templateBaseClass;
AbstractMetaFunctionCList m_functions;
+ AbstractMetaFunctionCList m_userAddedPythonOverrides;
AbstractMetaFieldList m_fields;
AbstractMetaEnumList m_enums;
QList<QPropertySpec> m_propertySpecs;
@@ -108,8 +112,8 @@ public:
AbstractMetaFunctionCList m_externalConversionOperators;
QStringList m_baseClassNames; // Base class names from C++, including rejected
- TypeEntries m_templateArgs;
- ComplexTypeEntry *m_typeEntry = nullptr;
+ TypeEntryCList m_templateArgs;
+ ComplexTypeEntryPtr m_typeEntry;
SourceLocation m_sourceLocation;
UsingMembers m_usingMembers;
@@ -174,29 +178,16 @@ AbstractMetaFunctionCList AbstractMetaClass::functionsInTargetLang() const
FunctionQueryOptions default_flags = FunctionQueryOption::NormalFunctions
| FunctionQueryOption::Visible | FunctionQueryOption::NotRemoved;
- // Only public functions in final classes
- // default_flags |= isFinal() ? WasPublic : 0;
- FunctionQueryOptions public_flags;
- if (isFinalInTargetLang())
- public_flags |= FunctionQueryOption::WasPublic;
-
// Constructors
AbstractMetaFunctionCList returned = queryFunctions(FunctionQueryOption::AnyConstructor
- | default_flags | public_flags);
-
- // Final functions
- returned += queryFunctions(FunctionQueryOption::FinalInTargetLangFunctions
- | FunctionQueryOption::NonStaticFunctions
- | default_flags | public_flags);
+ | default_flags);
- // Virtual functions
- returned += queryFunctions(FunctionQueryOption::VirtualInTargetLangFunctions
- | FunctionQueryOption::NonStaticFunctions
- | default_flags | public_flags);
+ returned += queryFunctions(FunctionQueryOption::NonStaticFunctions
+ | default_flags);
// Static functions
returned += queryFunctions(FunctionQueryOption::StaticFunctions
- | default_flags | public_flags);
+ | default_flags);
// Empty, private functions, since they aren't caught by the other ones
returned += queryFunctions(FunctionQueryOption::Empty | FunctionQueryOption::Invisible);
@@ -315,15 +306,15 @@ bool AbstractMetaClass::hasStaticFields() const
void AbstractMetaClass::sortFunctions()
{
- std::sort(d->m_functions.begin(), d->m_functions.end(), function_sorter);
+ d->sortFunctions();
}
-const AbstractMetaClass *AbstractMetaClass::templateBaseClass() const
+AbstractMetaClassCPtr AbstractMetaClass::templateBaseClass() const
{
return d->m_templateBaseClass;
}
-void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClass *cls)
+void AbstractMetaClass::setTemplateBaseClass(const AbstractMetaClassCPtr &cls)
{
d->m_templateBaseClass = cls;
}
@@ -333,17 +324,28 @@ const AbstractMetaFunctionCList &AbstractMetaClass::functions() const
return d->m_functions;
}
-void AbstractMetaClass::setFunctions(const AbstractMetaFunctionCList &functions)
+const AbstractMetaFunctionCList &AbstractMetaClass::userAddedPythonOverrides() const
+{
+ return d->m_userAddedPythonOverrides;
+}
+
+void AbstractMetaClassPrivate::sortFunctions()
+{
+ std::sort(m_functions.begin(), m_functions.end(), function_sorter);
+}
+
+void AbstractMetaClassPrivate::setFunctions(const AbstractMetaFunctionCList &functions,
+ const AbstractMetaClassCPtr &q)
{
- d->m_functions = functions;
+ m_functions = functions;
// Functions must be sorted by name before next loop
sortFunctions();
- for (const auto &f : qAsConst(d->m_functions)) {
- qSharedPointerConstCast<AbstractMetaFunction>(f)->setOwnerClass(this);
+ for (const auto &f : std::as_const(m_functions)) {
+ std::const_pointer_cast<AbstractMetaFunction>(f)->setOwnerClass(q);
if (!f->isPublic())
- d->m_hasNonpublic = true;
+ m_hasNonpublic = true;
}
}
@@ -357,6 +359,13 @@ void AbstractMetaClass::addPropertySpec(const QPropertySpec &spec)
d->m_propertySpecs << spec;
}
+void AbstractMetaClass::setPropertyDocumentation(const QString &name, const Documentation &doc)
+{
+ const auto index = d->indexOfProperty(name);
+ if (index >= 0)
+ d->m_propertySpecs[index].setDocumentation(doc);
+}
+
void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &function)
{
Q_ASSERT(!function->signature().startsWith(u'('));
@@ -373,20 +382,27 @@ void AbstractMetaClassPrivate::addFunction(const AbstractMetaFunctionCPtr &funct
&& function->functionType() == AbstractMetaFunction::ConstructorFunction;
}
-void AbstractMetaClass::addFunction(const AbstractMetaFunctionCPtr &function)
+void AbstractMetaClass::addFunction(const AbstractMetaClassPtr &klass,
+ const AbstractMetaFunctionCPtr &function)
{
- auto nonConstF = qSharedPointerConstCast<AbstractMetaFunction>(function);
- nonConstF->setOwnerClass(this);
+ auto nonConstF = std::const_pointer_cast<AbstractMetaFunction>(function);
+ nonConstF->setOwnerClass(klass);
// Set the default value of the declaring class. This may be changed
// in fixFunctions later on
- nonConstF->setDeclaringClass(this);
+ nonConstF->setDeclaringClass(klass);
// Some of the queries below depend on the implementing class being set
// to function properly. Such as function modifications
- nonConstF->setImplementingClass(this);
+ nonConstF->setImplementingClass(klass);
- d->addFunction(function);
+ if (function->isUserAddedPythonOverride()) {
+ nonConstF->setConstant(false);
+ nonConstF->setCppAttribute(FunctionAttribute::Static);
+ klass->d->m_userAddedPythonOverrides.append(function);
+ } else {
+ klass->d->addFunction(function);
+ }
}
bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
@@ -424,17 +440,17 @@ QString AbstractMetaClass::baseClassName() const
}
// Attribute "default-superclass"
-const AbstractMetaClass *AbstractMetaClass::defaultSuperclass() const
+AbstractMetaClassCPtr AbstractMetaClass::defaultSuperclass() const
{
return d->m_defaultSuperclass;
}
-void AbstractMetaClass::setDefaultSuperclass(AbstractMetaClass *s)
+void AbstractMetaClass::setDefaultSuperclass(const AbstractMetaClassPtr &s)
{
d->m_defaultSuperclass = s;
}
-const AbstractMetaClass *AbstractMetaClass::baseClass() const
+AbstractMetaClassCPtr AbstractMetaClass::baseClass() const
{
return d->m_baseClasses.value(0, nullptr);
}
@@ -449,7 +465,7 @@ const AbstractMetaClassCList &AbstractMetaClass::baseClasses() const
AbstractMetaClassCList AbstractMetaClass::typeSystemBaseClasses() const
{
AbstractMetaClassCList result = d->m_baseClasses;
- if (d->m_defaultSuperclass != nullptr) {
+ if (d->m_defaultSuperclass) {
result.removeAll(d->m_defaultSuperclass);
result.prepend(d->m_defaultSuperclass);
}
@@ -461,21 +477,21 @@ AbstractMetaClassCList AbstractMetaClass::allTypeSystemAncestors() const
{
AbstractMetaClassCList result;
const auto baseClasses = typeSystemBaseClasses();
- for (auto *base : baseClasses) {
+ for (const auto &base : baseClasses) {
result.append(base);
result.append(base->allTypeSystemAncestors());
}
return result;
}
-void AbstractMetaClass::addBaseClass(const AbstractMetaClass *baseClass)
+void AbstractMetaClass::addBaseClass(const AbstractMetaClassCPtr &baseClass)
{
Q_ASSERT(baseClass);
d->m_baseClasses.append(baseClass);
d->m_isPolymorphic |= baseClass->isPolymorphic();
}
-void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass)
+void AbstractMetaClass::setBaseClass(const AbstractMetaClassCPtr &baseClass)
{
if (baseClass) {
d->m_baseClasses.prepend(baseClass);
@@ -483,12 +499,12 @@ void AbstractMetaClass::setBaseClass(const AbstractMetaClass *baseClass)
}
}
-const AbstractMetaClass *AbstractMetaClass::extendedNamespace() const
+AbstractMetaClassCPtr AbstractMetaClass::extendedNamespace() const
{
return d->m_extendedNamespace;
}
-void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClass *e)
+void AbstractMetaClass::setExtendedNamespace(const AbstractMetaClassCPtr &e)
{
d->m_extendedNamespace = e;
}
@@ -498,7 +514,7 @@ const AbstractMetaClassCList &AbstractMetaClass::innerClasses() const
return d->m_innerClasses;
}
-void AbstractMetaClass::addInnerClass(AbstractMetaClass *cl)
+void AbstractMetaClass::addInnerClass(const AbstractMetaClassPtr &cl)
{
d->m_innerClasses << cl;
}
@@ -526,6 +542,16 @@ bool AbstractMetaClass::isInvisibleNamespace() const
&& !NamespaceTypeEntry::isVisibleScope(d->m_typeEntry);
}
+bool AbstractMetaClass::isInlineNamespace() const
+{
+ bool result = false;
+ if (d->m_typeEntry->isNamespace()) {
+ const auto nte = std::static_pointer_cast<const NamespaceTypeEntry>(d->m_typeEntry);
+ result = nte->isInlineNamespace();
+ }
+ return result;
+}
+
bool AbstractMetaClass::isQtNamespace() const
{
return isNamespace() && name() == u"Qt";
@@ -538,15 +564,15 @@ QString AbstractMetaClass::qualifiedCppName() const
bool AbstractMetaClass::hasFunction(const QString &str) const
{
- return !findFunction(str).isNull();
+ return bool(findFunction(str));
}
-AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QStringView functionName) const
+AbstractMetaFunctionCPtr AbstractMetaClass::findFunction(QAnyStringView functionName) const
{
return AbstractMetaFunction::find(d->m_functions, functionName);
}
-AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QStringView functionName) const
+AbstractMetaFunctionCList AbstractMetaClass::findFunctions(QAnyStringView functionName) const
{
AbstractMetaFunctionCList result;
std::copy_if(d->m_functions.cbegin(), d->m_functions.cend(),
@@ -588,12 +614,12 @@ bool AbstractMetaClass::hasProtectedFields() const
return false;
}
-const TypeEntries &AbstractMetaClass::templateArguments() const
+const TypeEntryCList &AbstractMetaClass::templateArguments() const
{
return d->m_templateArgs;
}
-void AbstractMetaClass::setTemplateArguments(const TypeEntries &args)
+void AbstractMetaClass::setTemplateArguments(const TypeEntryCList &args)
{
d->m_templateArgs = args;
}
@@ -608,17 +634,17 @@ void AbstractMetaClass::setBaseClassNames(const QStringList &names)
d->m_baseClassNames = names;
}
-const ComplexTypeEntry *AbstractMetaClass::typeEntry() const
+ComplexTypeEntryCPtr AbstractMetaClass::typeEntry() const
{
return d->m_typeEntry;
}
-ComplexTypeEntry *AbstractMetaClass::typeEntry()
+ComplexTypeEntryPtr AbstractMetaClass::typeEntry()
{
return d->m_typeEntry;
}
-void AbstractMetaClass::setTypeEntry(ComplexTypeEntry *type)
+void AbstractMetaClass::setTypeEntry(const ComplexTypeEntryPtr &type)
{
d->m_typeEntry = type;
}
@@ -642,7 +668,7 @@ bool AbstractMetaClass::hasHashFunction() const
AbstractMetaClass::PropertyFunctionSearchResult
AbstractMetaClass::searchPropertyFunction(const QString &name) const
{
- for (int i = 0, size = d->m_propertySpecs.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = d->m_propertySpecs.size(); i < size; ++i) {
const auto &propertySpec = d->m_propertySpecs.at(i);
if (name == propertySpec.read())
return PropertyFunctionSearchResult{i, PropertyFunction::Read};
@@ -650,6 +676,8 @@ AbstractMetaClass::PropertyFunctionSearchResult
return PropertyFunctionSearchResult{i, PropertyFunction::Write};
if (name == propertySpec.reset())
return PropertyFunctionSearchResult{i, PropertyFunction::Reset};
+ if (name == propertySpec.notify())
+ return PropertyFunctionSearchResult{i, PropertyFunction::Notify};
}
return PropertyFunctionSearchResult{-1, PropertyFunction::Read};
}
@@ -657,10 +685,9 @@ AbstractMetaClass::PropertyFunctionSearchResult
std::optional<QPropertySpec>
AbstractMetaClass::propertySpecByName(const QString &name) const
{
- for (const auto &propertySpec : d->m_propertySpecs) {
- if (name == propertySpec.name())
- return propertySpec;
- }
+ const auto index = d->indexOfProperty(name);
+ if (index >= 0)
+ return d->m_propertySpecs.at(index);
return {};
}
@@ -745,6 +772,15 @@ bool AbstractMetaClassPrivate::hasConstructors() const
FunctionQueryOption::AnyConstructor) != nullptr;
}
+qsizetype AbstractMetaClassPrivate::indexOfProperty(const QString &name) const
+{
+ for (qsizetype i = 0; i < m_propertySpecs.size(); ++i) {
+ if (m_propertySpecs.at(i).name() == name)
+ return i;
+ }
+ return -1;
+}
+
bool AbstractMetaClass::hasConstructors() const
{
return d->hasConstructors();
@@ -767,41 +803,40 @@ bool AbstractMetaClass::hasCopyConstructor() const
bool AbstractMetaClass::hasPrivateCopyConstructor() const
{
const auto copyCt = copyConstructor();
- return !copyCt.isNull() && copyCt->isPrivate();
+ return copyCt && copyCt->isPrivate();
}
void AbstractMetaClassPrivate::addConstructor(AbstractMetaFunction::FunctionType t,
Access access,
const AbstractMetaArgumentList &arguments,
- AbstractMetaClass *q)
+ const AbstractMetaClassPtr &q)
{
auto *f = createFunction(q->name(), t, access, arguments, AbstractMetaType::createVoid(), q);
if (access != Access::Private)
m_hasNonPrivateConstructor = true;
- f->setAttributes(AbstractMetaFunction::FinalInTargetLang
- | AbstractMetaFunction::AddedMethod);
+ f->setAttributes(AbstractMetaFunction::AddedMethod);
addFunction(AbstractMetaFunctionCPtr(f));
}
-void AbstractMetaClass::addDefaultConstructor()
+void AbstractMetaClass::addDefaultConstructor(const AbstractMetaClassPtr &klass)
{
- d->addConstructor(AbstractMetaFunction::ConstructorFunction,
- Access::Public, {}, this);
+ klass->d->addConstructor(AbstractMetaFunction::ConstructorFunction,
+ Access::Public, {}, klass);
}
-void AbstractMetaClass::addDefaultCopyConstructor()
+void AbstractMetaClass::addDefaultCopyConstructor(const AbstractMetaClassPtr &klass)
{
- AbstractMetaType argType(typeEntry());
+ AbstractMetaType argType(klass->typeEntry());
argType.setReferenceType(LValueReference);
argType.setConstant(true);
argType.setTypeUsagePattern(AbstractMetaType::ValuePattern);
AbstractMetaArgument arg;
arg.setType(argType);
- arg.setName(name());
+ arg.setName(klass->name());
- d->addConstructor(AbstractMetaFunction::CopyConstructorFunction,
- Access::Public, {arg}, this);
+ klass->d->addConstructor(AbstractMetaFunction::CopyConstructorFunction,
+ Access::Public, {arg}, klass);
}
AbstractMetaFunction *
@@ -810,7 +845,7 @@ AbstractMetaFunction *
Access access,
const AbstractMetaArgumentList &arguments,
const AbstractMetaType &returnType,
- AbstractMetaClass *q)
+ const AbstractMetaClassPtr &q)
{
auto *f = new AbstractMetaFunction(name);
f->setType(returnType);
@@ -825,7 +860,7 @@ AbstractMetaFunction *
static AbstractMetaType boolType()
{
- auto *boolType = TypeDatabase::instance()->findType(u"bool"_s);
+ auto boolType = TypeDatabase::instance()->findType(u"bool"_s);
Q_ASSERT(boolType);
AbstractMetaType result(boolType);
result.decideUsagePattern();
@@ -835,17 +870,17 @@ static AbstractMetaType boolType()
// Helper to synthesize comparison operators from a spaceship operator. Since
// shiboken also generates code for comparing to different types, this fits
// better than of handling it in the generator code.
-void AbstractMetaClass::addSynthesizedComparisonOperators()
+void AbstractMetaClass::addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c)
{
static const auto returnType = boolType();
- AbstractMetaType selfType(typeEntry());
+ AbstractMetaType selfType(c->typeEntry());
selfType.setConstant(true);
selfType.setReferenceType(LValueReference);
selfType.decideUsagePattern();
AbstractMetaArgument selfArgument;
selfArgument.setType(selfType);
- selfArgument.setName(u"rhs"_qs);
+ selfArgument.setName(u"rhs"_s);
AbstractMetaArgumentList arguments(1, selfArgument);
static const char *operators[]
@@ -854,8 +889,8 @@ void AbstractMetaClass::addSynthesizedComparisonOperators()
auto *f = AbstractMetaClassPrivate::createFunction(QLatin1StringView(op),
AbstractMetaFunction::ComparisonOperator,
Access::Public, arguments,
- returnType, this);
- d->addFunction(AbstractMetaFunctionCPtr(f));
+ returnType, c);
+ c->d->addFunction(AbstractMetaFunctionCPtr(f));
}
}
@@ -961,7 +996,7 @@ bool AbstractMetaClass::isImplicitlyDefaultConstructible() const
return std::all_of(d->m_fields.cbegin(), d->m_fields.cend(),
defaultConstructibleField)
&& std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(),
- [] (const AbstractMetaClass *c) {
+ [] (const AbstractMetaClassCPtr &c) {
return c->isDefaultConstructible();
});
}
@@ -969,6 +1004,7 @@ bool AbstractMetaClass::isImplicitlyDefaultConstructible() const
static bool canAddDefaultConstructorHelper(const AbstractMetaClass *cls)
{
return !cls->isNamespace()
+ && !cls->hasDeletedDefaultConstructor()
&& !cls->attributes().testFlag(AbstractMetaClass::HasRejectedConstructor)
&& !cls->hasPrivateDestructor();
}
@@ -995,7 +1031,7 @@ bool AbstractMetaClass::isImplicitlyCopyConstructible() const
{
// Fields are currently not considered
return std::all_of(d->m_baseClasses.cbegin(), d->m_baseClasses.cend(),
- [] (const AbstractMetaClass *c) {
+ [] (const AbstractMetaClassCPtr &c) {
return c->isCopyConstructible();
});
}
@@ -1010,16 +1046,16 @@ bool AbstractMetaClass::canAddDefaultCopyConstructor() const
return isImplicitlyCopyConstructible();
}
-static bool classHasParentManagement(const AbstractMetaClass *c)
+static bool classHasParentManagement(const AbstractMetaClassCPtr &c)
{
const auto flags = c->typeEntry()->typeFlags();
return flags.testFlag(ComplexTypeEntry::ParentManagement);
}
-const TypeEntry *AbstractMetaClass::parentManagementEntry() const
+TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass)
{
- if (isObjectType()) {
- if (auto *c = recurseClassHierarchy(this, classHasParentManagement))
+ if (klass->typeEntry()->isObject()) {
+ if (auto c = recurseClassHierarchy(klass, classHasParentManagement))
return c->typeEntry();
}
return nullptr;
@@ -1089,7 +1125,7 @@ void AbstractMetaClass::addUsingMember(const UsingMember &um)
d->m_usingMembers.append(um);
}
-bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c,
+bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClassCPtr &c,
const QString &memberName,
Access minimumAccess) const
{
@@ -1100,7 +1136,7 @@ bool AbstractMetaClassPrivate::isUsingMember(const AbstractMetaClass *c,
return it != m_usingMembers.cend() && it->access >= minimumAccess;
}
-bool AbstractMetaClass::isUsingMember(const AbstractMetaClass *c,
+bool AbstractMetaClass::isUsingMember(const AbstractMetaClassCPtr &c,
const QString &memberName,
Access minimumAccess) const
{
@@ -1131,24 +1167,15 @@ bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQue
if (query.testFlag(FunctionQueryOption::Visible) && f->isPrivate())
return false;
- if (query.testFlag(FunctionQueryOption::VirtualInTargetLangFunctions) && f->isFinalInTargetLang())
- return false;
-
if (query.testFlag(FunctionQueryOption::Invisible) && !f->isPrivate())
return false;
if (query.testFlag(FunctionQueryOption::Empty) && !f->isEmptyFunction())
return false;
- if (query.testFlag(FunctionQueryOption::WasPublic) && !f->wasPublic())
- return false;
-
if (query.testFlag(FunctionQueryOption::ClassImplements) && f->ownerClass() != f->implementingClass())
return false;
- if (query.testFlag(FunctionQueryOption::FinalInTargetLangFunctions) && !f->isFinalInTargetLang())
- return false;
-
if (query.testFlag(FunctionQueryOption::VirtualInCppFunctions) && !f->isVirtual())
return false;
@@ -1212,7 +1239,7 @@ AbstractMetaFunctionCList AbstractMetaClass::queryFunctionList(const AbstractMet
{
AbstractMetaFunctionCList result;
for (const auto &f : list) {
- if (queryFunction(f.data(), query))
+ if (queryFunction(f.get(), query))
result.append(f);
}
return result;
@@ -1222,7 +1249,7 @@ AbstractMetaFunctionCPtr AbstractMetaClass::queryFirstFunction(const AbstractMet
FunctionQueryOptions query)
{
for (const auto &f : list) {
- if (queryFunction(f.data(), query))
+ if (queryFunction(f.get(), query))
return f;
}
return {};
@@ -1290,7 +1317,7 @@ std::optional<AbstractMetaEnum>
std::optional<AbstractMetaEnumValue>
AbstractMetaClass::findEnumValue(const QString &enumValueName) const
{
- for (const AbstractMetaEnum &e : qAsConst(d->m_enums)) {
+ for (const AbstractMetaEnum &e : std::as_const(d->m_enums)) {
auto v = e.findEnumValue(enumValueName);
if (v.has_value())
return v;
@@ -1312,7 +1339,7 @@ void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) co
void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const
{
if (isNamespace()) {
- invisibleNamespaceRecursion([enumList](const AbstractMetaClass *c) {
+ invisibleNamespaceRecursion([enumList](const AbstractMetaClassCPtr &c) {
c->getEnumsToBeGenerated(enumList);
});
}
@@ -1321,7 +1348,7 @@ void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMet
void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionCList *funcList) const
{
if (isNamespace()) {
- invisibleNamespaceRecursion([funcList](const AbstractMetaClass *c) {
+ invisibleNamespaceRecursion([funcList](const AbstractMetaClassCPtr &c) {
funcList->append(c->functions());
});
}
@@ -1332,16 +1359,16 @@ QString AbstractMetaClass::fullName() const
return package() + u'.' + d->m_typeEntry->targetLangName();
}
-static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType &type)
+static void addExtraIncludeForType(const AbstractMetaClassPtr &metaClass,
+ const AbstractMetaType &type)
{
Q_ASSERT(metaClass);
- const TypeEntry *entry = type.typeEntry();
- if (entry && entry->isComplex()) {
- const auto *centry = static_cast<const ComplexTypeEntry *>(entry);
- ComplexTypeEntry *class_entry = metaClass->typeEntry();
- if (class_entry && centry->include().isValid())
- class_entry->addArgumentInclude(centry->include());
+ const auto entry = type.typeEntry();
+
+ if (entry && entry->include().isValid()) {
+ const auto class_entry = metaClass->typeEntry();
+ class_entry->addArgumentInclude(entry->include());
}
if (type.hasInstantiations()) {
@@ -1350,7 +1377,7 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM
}
}
-static void addExtraIncludesForFunction(AbstractMetaClass *metaClass,
+static void addExtraIncludesForFunction(const AbstractMetaClassPtr &metaClass,
const AbstractMetaFunctionCPtr &meta_function)
{
Q_ASSERT(metaClass);
@@ -1358,8 +1385,12 @@ static void addExtraIncludesForFunction(AbstractMetaClass *metaClass,
addExtraIncludeForType(metaClass, meta_function->type());
const AbstractMetaArgumentList &arguments = meta_function->arguments();
- for (const AbstractMetaArgument &argument : arguments)
- addExtraIncludeForType(metaClass, argument.type());
+ for (const AbstractMetaArgument &argument : arguments) {
+ const auto &type = argument.type();
+ addExtraIncludeForType(metaClass, type);
+ if (argument.modifiedType() != type)
+ addExtraIncludeForType(metaClass, argument.modifiedType());
+ }
}
static bool addSuperFunction(const AbstractMetaFunctionCPtr &f)
@@ -1381,7 +1412,7 @@ static bool addSuperFunction(const AbstractMetaFunctionCPtr &f)
// Add constructors imported via "using" from the base classes. This is not
// needed for normal hidden inherited member functions since we generate a
// cast to the base class to call them into binding code.
-void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q)
+void AbstractMetaClassPrivate::addUsingConstructors(const AbstractMetaClassPtr &q)
{
// Restricted to the non-constructor case currently to avoid
// having to compare the parameter lists of existing constructors.
@@ -1390,7 +1421,7 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q)
return;
}
- for (auto superClass : m_baseClasses) {
+ for (const auto &superClass : m_baseClasses) {
// Find any "using base-constructor" directives
if (isUsingMember(superClass, superClass->name(), Access::Protected)) {
// Add to derived class with parameter lists.
@@ -1405,51 +1436,61 @@ void AbstractMetaClassPrivate::addUsingConstructors(AbstractMetaClass *q)
}
}
-void AbstractMetaClass::fixFunctions()
+static inline bool isSignal(const AbstractMetaFunctionCPtr &f)
+{
+ return f->isSignal();
+}
+
+void AbstractMetaClass::fixFunctions(const AbstractMetaClassPtr &klass)
{
+ auto *d = klass->d.data();
if (d->m_functionsFixed)
return;
d->m_functionsFixed = true;
- AbstractMetaFunctionCList funcs = functions();
+ AbstractMetaFunctionCList funcs = klass->functions();
AbstractMetaFunctionCList nonRemovedFuncs;
nonRemovedFuncs.reserve(funcs.size());
- d->addUsingConstructors(this);
+ d->addUsingConstructors(klass);
- for (const auto &f : qAsConst(funcs)) {
+ for (const auto &f : std::as_const(funcs)) {
// Fishy: Setting up of implementing/declaring/base classes changes
// the applicable modifications; clear cached ones.
- qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache();
+ std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache();
if (!f->isModifiedRemoved())
nonRemovedFuncs.append(f);
}
- for (auto *superClassC : d->m_baseClasses) {
- auto *superClass = const_cast<AbstractMetaClass *>(superClassC);
- superClass->fixFunctions();
+ for (const auto &superClassC : d->m_baseClasses) {
+ for (const auto &pof : superClassC->userAddedPythonOverrides()) {
+ auto *clonedPof = pof->copy();
+ clonedPof->setOwnerClass(klass);
+ d->m_userAddedPythonOverrides.append(AbstractMetaFunctionCPtr{clonedPof});
+ }
+
+ auto superClass = std::const_pointer_cast<AbstractMetaClass>(superClassC);
+ AbstractMetaClass::fixFunctions(superClass);
// Since we always traverse the complete hierarchy we are only
// interrested in what each super class implements, not what
// we may have propagated from their base classes again.
AbstractMetaFunctionCList superFuncs;
- // Super classes can never be final
- if (superClass->isFinalInTargetLang()) {
- qCWarning(lcShiboken).noquote().nospace()
- << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes";
- *superClass -= AbstractMetaClass::FinalInTargetLang;
- }
superFuncs = superClass->queryFunctions(FunctionQueryOption::ClassImplements);
+ // We are not interested in signals as no bindings are generated for them;
+ // they cause documentation warnings.
+ superFuncs.erase(std::remove_if(superFuncs.begin(), superFuncs.end(), isSignal),
+ superFuncs.end());
const auto virtuals = superClass->queryFunctions(FunctionQueryOption::VirtualInCppFunctions);
superFuncs += virtuals;
QSet<AbstractMetaFunctionCPtr> funcsToAdd;
- for (const auto &sf : qAsConst(superFuncs)) {
+ for (const auto &sf : std::as_const(superFuncs)) {
if (sf->isModifiedRemoved())
continue;
// skip functions added in base classes
- if (sf->isUserAdded() && sf->declaringClass() != this)
+ if (sf->isUserAdded() && sf->declaringClass() != klass)
continue;
// Skip base class comparison operators declared as members (free
@@ -1460,43 +1501,25 @@ void AbstractMetaClass::fixFunctions()
// we generally don't care about private functions, but we have to get the ones that are
// virtual in case they override abstract functions.
bool add = addSuperFunction(sf);
- for (const auto &cf : qAsConst(nonRemovedFuncs)) {
- AbstractMetaFunctionPtr f(qSharedPointerConstCast<AbstractMetaFunction>(cf));
- const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.data());
+ for (const auto &cf : std::as_const(nonRemovedFuncs)) {
+ AbstractMetaFunctionPtr f(std::const_pointer_cast<AbstractMetaFunction>(cf));
+ const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.get());
if (cmp & AbstractMetaFunction::EqualModifiedName) {
add = false;
if (cmp & AbstractMetaFunction::EqualArguments) {
// Set "override" in case it was not spelled out (since it
// is then not detected by clang parsing).
- const auto attributes = cf->attributes();
- if (cf->isVirtual()
- && !attributes.testFlag(AbstractMetaFunction::OverriddenCppMethod)
- && !attributes.testFlag(AbstractMetaFunction::FinalCppMethod)) {
- *f += AbstractMetaFunction::OverriddenCppMethod;
- }
- // Same function, propegate virtual...
- if (!(cmp & AbstractMetaFunction::EqualAttributes)) {
- if (!f->isEmptyFunction()) {
- if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) {
- *f -= AbstractMetaFunction::FinalInTargetLang;
- }
-#if 0
- if (!f->isFinalInTargetLang() && f->isPrivate()) {
- f->setFunctionType(AbstractMetaFunction::EmptyFunction);
- f->setVisibility(AbstractMetaAttributes::Protected);
- *f += AbstractMetaAttributes::FinalInTargetLang;
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("private virtual function '%1' in '%2'")
- .arg(f->signature(), f->implementingClass()->name());
- }
-#endif
- }
+ const auto attributes = cf->cppAttributes();
+ if (attributes.testFlag(FunctionAttribute::Virtual)
+ && !attributes.testFlag(FunctionAttribute::Override)
+ && !attributes.testFlag(FunctionAttribute::Final)) {
+ f->setCppAttribute(FunctionAttribute::Override);
}
if (f->access() != sf->access()) {
qCWarning(lcShiboken, "%s",
- qPrintable(msgFunctionVisibilityModified(this, f.data())));
+ qPrintable(msgFunctionVisibilityModified(klass, f.get())));
#if 0
// If new visibility is private, we can't
// do anything. If it isn't, then we
@@ -1508,43 +1531,12 @@ void AbstractMetaClass::fixFunctions()
// Private overrides of abstract functions have to go into the class or
// the subclasses will not compile as non-abstract classes.
// But they don't need to be implemented, since they can never be called.
- if (f->isPrivate()) {
+ if (f->isPrivate())
f->setFunctionType(AbstractMetaFunction::EmptyFunction);
- *f += AbstractMetaFunction::FinalInTargetLang;
- }
}
// Set the class which first declares this function, afawk
f->setDeclaringClass(sf->declaringClass());
-
- if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) {
- // Shadowed funcion, need to make base class
- // function non-virtual
- if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) {
-
- // Check whether the superclass method has been redefined to non-final
-
- bool hasNonFinalModifier = false;
- bool isBaseImplPrivate = false;
- const FunctionModificationList &mods = sf->modifications(sf->implementingClass());
- for (const FunctionModification &mod : mods) {
- if (mod.isNonFinal()) {
- hasNonFinalModifier = true;
- break;
- }
- if (mod.isPrivate()) {
- isBaseImplPrivate = true;
- break;
- }
- }
-
- if (!hasNonFinalModifier && !isBaseImplPrivate) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgShadowingFunction(sf.data(), f.data())));
- }
- }
- }
-
}
if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
@@ -1572,7 +1564,7 @@ void AbstractMetaClass::fixFunctions()
funcsToAdd << sf;
}
- for (const auto &f : qAsConst(funcsToAdd)) {
+ for (const auto &f : std::as_const(funcsToAdd)) {
AbstractMetaFunction *copy = f->copy();
(*copy) += AbstractMetaFunction::AddedMethod;
funcs.append(AbstractMetaFunctionCPtr(copy));
@@ -1582,9 +1574,9 @@ void AbstractMetaClass::fixFunctions()
bool hasPrivateConstructors = false;
bool hasPublicConstructors = false;
// Apply modifications after the declaring class has been set
- for (const auto &func : qAsConst(funcs)) {
- auto ncFunc = qSharedPointerConstCast<AbstractMetaFunction>(func);
- for (const auto &mod : func->modifications(this)) {
+ for (const auto &func : std::as_const(funcs)) {
+ auto ncFunc = std::const_pointer_cast<AbstractMetaFunction>(func);
+ for (const auto &mod : func->modifications(klass)) {
if (mod.isRenameModifier())
ncFunc->setName(mod.renamedToName());
}
@@ -1592,8 +1584,8 @@ void AbstractMetaClass::fixFunctions()
// Make sure class is abstract if one of the functions is
if (func->isAbstract()) {
- (*this) += AbstractMetaClass::Abstract;
- (*this) -= AbstractMetaClass::FinalInTargetLang;
+ (*klass) += AbstractMetaClass::Abstract;
+ (*klass) -= AbstractMetaClass::FinalInTargetLang;
}
if (func->isConstructor()) {
@@ -1606,15 +1598,15 @@ void AbstractMetaClass::fixFunctions()
// Make sure that we include files for all classes that are in use
- addExtraIncludesForFunction(this, func);
+ addExtraIncludesForFunction(klass, func);
}
if (hasPrivateConstructors && !hasPublicConstructors) {
- (*this) += AbstractMetaClass::Abstract;
- (*this) -= AbstractMetaClass::FinalInTargetLang;
+ (*klass) += AbstractMetaClass::Abstract;
+ (*klass) -= AbstractMetaClass::FinalInTargetLang;
}
- setFunctions(funcs);
+ d->setFunctions(funcs, klass);
}
bool AbstractMetaClass::needsInheritanceSetup() const
@@ -1623,6 +1615,7 @@ bool AbstractMetaClass::needsInheritanceSetup() const
switch (d->m_typeEntry->type()) {
case TypeEntry::NamespaceType:
case TypeEntry::SmartPointerType:
+ case TypeEntry::ContainerType:
return false;
default:
break;
@@ -1654,11 +1647,11 @@ std::optional<AbstractMetaEnumValue>
if (lst.size() > 1) {
const auto &prefixName = lst.at(0);
const auto &enumName = lst.at(1);
- if (auto *cl = findClass(classes, prefixName))
+ if (auto cl = findClass(classes, prefixName))
return cl->findEnumValue(enumName.toString());
}
- for (AbstractMetaClass *metaClass : classes) {
+ for (const auto &metaClass : classes) {
auto enumValue = metaClass->findEnumValue(name);
if (enumValue.has_value())
return enumValue;
@@ -1672,12 +1665,12 @@ std::optional<AbstractMetaEnumValue>
/// Target language base name or complete Target language package.class name.
template <class It>
-static It findClassHelper(It begin, It end, QStringView name)
+static It findClassHelper(It begin, It end, QAnyStringView name)
{
if (name.isEmpty() || begin == end)
return end;
- if (name.contains(u'.')) { // Search target lang name
+ if (asv_contains(name,'.')) { // Search target lang name
for (auto it = begin; it != end; ++it) {
if ((*it)->fullName() == name)
return it;
@@ -1690,7 +1683,7 @@ static It findClassHelper(It begin, It end, QStringView name)
return it;
}
- if (name.contains(u"::")) // Qualified, cannot possibly match name
+ if (asv_contains(name, "::")) // Qualified, cannot possibly match name
return end;
for (auto it = begin; it != end; ++it) {
@@ -1701,32 +1694,32 @@ static It findClassHelper(It begin, It end, QStringView name)
return end;
}
-AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
- QStringView name)
+AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
+ QAnyStringView name)
{
auto it =findClassHelper(classes.cbegin(), classes.cend(), name);
return it != classes.cend() ? *it : nullptr;
}
-const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes,
- QStringView name)
+AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes,
+ QAnyStringView name)
{
auto it = findClassHelper(classes.cbegin(), classes.cend(), name);
return it != classes.cend() ? *it : nullptr;
}
-AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
- const TypeEntry *typeEntry)
+AbstractMetaClassPtr AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
+ const TypeEntryCPtr &typeEntry)
{
- for (AbstractMetaClass *c : classes) {
+ for (AbstractMetaClassPtr c : classes) {
if (c->typeEntry() == typeEntry)
return c;
}
return nullptr;
}
-const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCList &classes,
- const TypeEntry *typeEntry)
+AbstractMetaClassCPtr AbstractMetaClass::findClass(const AbstractMetaClassCList &classes,
+ const TypeEntryCPtr &typeEntry)
{
for (auto c : classes) {
if (c->typeEntry() == typeEntry)
@@ -1736,40 +1729,41 @@ const AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassCLi
}
/// Returns true if this class is a subclass of the given class
-bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
+bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &cls)
{
Q_ASSERT(cls != nullptr);
- if (this == cls || d->m_templateBaseClass == cls)
+ if (c == cls || c->templateBaseClass() == cls)
return true;
- return recurseClassHierarchy(this, [cls](const AbstractMetaClass *c) {
- return cls == c;
- }) != nullptr;
+ return bool(recurseClassHierarchy(c, [cls](const AbstractMetaClassCPtr &c) {
+ return cls.get() == c.get();
+ }));
}
-bool AbstractMetaClass::inheritsFrom(const QString &name) const
+bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name)
{
- if (this->qualifiedCppName() == name)
+ if (c->qualifiedCppName() == name)
return true;
- if (d->m_templateBaseClass != nullptr
- && d->m_templateBaseClass->qualifiedCppName() == name) {
+ if (c->templateBaseClass() != nullptr
+ && c->templateBaseClass()->qualifiedCppName() == name) {
return true;
}
- return recurseClassHierarchy(this, [&name](const AbstractMetaClass *c) {
+ return bool(recurseClassHierarchy(c, [&name](const AbstractMetaClassCPtr &c) {
return c->qualifiedCppName() == name;
- }) != nullptr;
+ }));
}
-const AbstractMetaClass *AbstractMetaClass::findBaseClass(const QString &qualifiedName) const
+AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c,
+ const QString &qualifiedName)
{
- if (d->m_templateBaseClass != nullptr
- && d->m_templateBaseClass->qualifiedCppName() == qualifiedName) {
- return d->m_templateBaseClass;
- }
- return recurseClassHierarchy(this, [&qualifiedName](const AbstractMetaClass *c) {
+ auto tp = c->templateBaseClass();
+ if (tp && tp->qualifiedCppName() == qualifiedName)
+ return tp;
+
+ return recurseClassHierarchy(c, [&qualifiedName](const AbstractMetaClassCPtr &c) {
return c->qualifiedCppName() == qualifiedName;
});
}
@@ -1799,7 +1793,7 @@ void AbstractMetaClass::setValueTypeWithCopyConstructorOnly(bool v)
d->m_valueTypeWithCopyConstructorOnly = v;
}
-bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c,
+bool AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c,
bool avoidProtectedHack)
{
@@ -1835,8 +1829,8 @@ void AbstractMetaClass::format(QDebug &debug) const
if (debug.verbosity() > 2)
debug << static_cast<const void *>(this) << ", ";
debug << '"' << qualifiedCppName();
- if (const int count = d->m_templateArgs.size()) {
- for (int i = 0; i < count; ++i)
+ if (const auto count = d->m_templateArgs.size()) {
+ for (qsizetype i = 0; i < count; ++i)
debug << (i ? ',' : '<') << d->m_templateArgs.at(i)->qualifiedCppName();
debug << '>';
}
@@ -1865,7 +1859,7 @@ void AbstractMetaClass::format(QDebug &debug) const
if (!d->m_baseClasses.isEmpty()) {
debug << ", inherits ";
- for (auto b : d->m_baseClasses)
+ for (const auto &b : d->m_baseClasses)
debug << " \"" << b->name() << '"';
}
@@ -1880,13 +1874,13 @@ void AbstractMetaClass::format(QDebug &debug) const
if (auto templateBase = templateBaseClass()) {
const auto &instantiatedTypes = templateBaseClassInstantiations();
debug << ", instantiates \"" << templateBase->name();
- for (int i = 0, count = instantiatedTypes.size(); i < count; ++i)
+ for (qsizetype i = 0, count = instantiatedTypes.size(); i < count; ++i)
debug << (i ? ',' : '<') << instantiatedTypes.at(i).name();
debug << ">\"";
}
- if (const int count = d->m_propertySpecs.size()) {
+ if (const auto count = d->m_propertySpecs.size()) {
debug << ", properties (" << count << "): [";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
debug << ", ";
d->m_propertySpecs.at(i).formatDebug(debug);
@@ -1900,18 +1894,18 @@ void AbstractMetaClass::formatMembers(QDebug &debug) const
if (!d->m_enums.isEmpty())
debug << ", enums[" << d->m_enums.size() << "]=" << d->m_enums;
if (!d->m_functions.isEmpty()) {
- const int count = d->m_functions.size();
+ const auto count = d->m_functions.size();
debug << ", functions=[" << count << "](";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
debug << ", ";
d->m_functions.at(i)->formatDebugBrief(debug);
}
debug << ')';
}
- if (const int count = d->m_fields.size()) {
+ if (const auto count = d->m_fields.size()) {
debug << ", fields=[" << count << "](";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
debug << ", ";
d->m_fields.at(i).formatDebug(debug);
@@ -1930,6 +1924,18 @@ void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation)
d->m_sourceLocation = sourceLocation;
}
+AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass)
+{
+ AbstractMetaClassCList result;
+ recurseClassHierarchy(metaClass, [&result] (const AbstractMetaClassCPtr &c) {
+ if (!result.contains(c))
+ result.append(c);
+ return false;
+ });
+ result.removeFirst(); // remove self
+ return result;
+}
+
QDebug operator<<(QDebug debug, const UsingMember &d)
{
QDebugStateSaver saver(debug);
@@ -1940,20 +1946,38 @@ QDebug operator<<(QDebug debug, const UsingMember &d)
return debug;
}
-QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
+void formatMetaClass(QDebug &ddebug, const AbstractMetaClass *ac)
{
- QDebugStateSaver saver(d);
- d.noquote();
- d.nospace();
- d << "AbstractMetaClass(";
- if (ac) {
- ac->format(d);
- if (d.verbosity() > 2)
- ac->formatMembers(d);
+ QDebugStateSaver saver(ddebug);
+ ddebug.noquote();
+ ddebug.nospace();
+ ddebug << "AbstractMetaClass(";
+ if (ac != nullptr) {
+ ac->format(ddebug);
+ if (ddebug.verbosity() > 2)
+ ac->formatMembers(ddebug);
} else {
- d << '0';
+ ddebug << '0';
}
- d << ')';
+ ddebug << ')';
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac)
+{
+ formatMetaClass(d, ac.get());
+ return d;
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac)
+{
+ formatMetaClass(d, ac.get());
return d;
}
+
+QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
+{
+ formatMetaClass(d, ac);
+ return d;
+}
+
#endif // !QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h
index 10543381a..3dc876690 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h
@@ -7,7 +7,6 @@
#include "abstractmetalang_enums.h"
#include "abstractmetalang_typedefs.h"
#include "enclosingclassmixin.h"
-#include "typesystem_enums.h"
#include "typesystem_typedefs.h"
#include <QtCore/qobjectdefs.h>
@@ -48,7 +47,8 @@ public:
HasRejectedDefaultConstructor = 0x00000020,
FinalCppClass = 0x00000100,
- Deprecated = 0x00000200
+ Deprecated = 0x00000200,
+ Struct = 0x00000400
};
Q_DECLARE_FLAGS(Attributes, Attribute)
Q_FLAG(Attribute)
@@ -66,11 +66,13 @@ public:
~AbstractMetaClass();
const AbstractMetaFunctionCList &functions() const;
+ const AbstractMetaFunctionCList &userAddedPythonOverrides() const;
void setFunctions(const AbstractMetaFunctionCList &functions);
- void addFunction(const AbstractMetaFunctionCPtr &function);
+ static void addFunction(const AbstractMetaClassPtr &klass,
+ const AbstractMetaFunctionCPtr &function);
bool hasFunction(const QString &str) const;
- AbstractMetaFunctionCPtr findFunction(QStringView functionName) const;
- AbstractMetaFunctionCList findFunctions(QStringView functionName) const;
+ AbstractMetaFunctionCPtr findFunction(QAnyStringView functionName) const;
+ AbstractMetaFunctionCList findFunctions(QAnyStringView functionName) const;
AbstractMetaFunctionCPtr findOperatorBool() const;
// Find a Qt-style isNull() method suitable for nb_bool
AbstractMetaFunctionCPtr findQtIsNullMethod() const;
@@ -81,8 +83,8 @@ public:
bool hasCopyConstructor() const;
bool hasPrivateCopyConstructor() const;
- void addDefaultConstructor();
- void addDefaultCopyConstructor();
+ static void addDefaultConstructor(const AbstractMetaClassPtr &klass);
+ static void addDefaultCopyConstructor(const AbstractMetaClassPtr &klass);
bool hasNonPrivateConstructor() const;
void setHasNonPrivateConstructor(bool value);
@@ -113,11 +115,7 @@ public:
bool isImplicitlyCopyConstructible() const;
bool canAddDefaultCopyConstructor() const;
- /// Return type entry of the base class that declares the parent management
- const TypeEntry *parentManagementEntry() const;
- bool hasParentManagement() const { return parentManagementEntry() != nullptr; }
-
- void addSynthesizedComparisonOperators();
+ static void addSynthesizedComparisonOperators(const AbstractMetaClassPtr &c);
bool generateExceptionHandling() const;
@@ -125,7 +123,7 @@ public:
const UsingMembers &usingMembers() const;
void addUsingMember(const UsingMember &um);
- bool isUsingMember(const AbstractMetaClass *c, const QString &memberName,
+ bool isUsingMember(const AbstractMetaClassCPtr &c, const QString &memberName,
Access minimumAccess) const;
bool hasUsingMemberFor(const QString &memberName) const;
@@ -190,42 +188,40 @@ public:
QString baseClassName() const;
- const AbstractMetaClass *defaultSuperclass() const; // Attribute "default-superclass"
- void setDefaultSuperclass(AbstractMetaClass *s);
+ AbstractMetaClassCPtr defaultSuperclass() const; // Attribute "default-superclass"
+ void setDefaultSuperclass(const AbstractMetaClassPtr &s);
- const AbstractMetaClass *baseClass() const;
+ AbstractMetaClassCPtr baseClass() const;
const AbstractMetaClassCList &baseClasses() const;
// base classes including defaultSuperclass
AbstractMetaClassCList typeSystemBaseClasses() const;
// Recursive list of all base classes including defaultSuperclass
AbstractMetaClassCList allTypeSystemAncestors() const;
- void addBaseClass(const AbstractMetaClass *base_class);
- void setBaseClass(const AbstractMetaClass *base_class);
+ void addBaseClass(const AbstractMetaClassCPtr &base_class);
+ void setBaseClass(const AbstractMetaClassCPtr &base_class);
/**
* \return the namespace from another package which this namespace extends.
*/
- const AbstractMetaClass *extendedNamespace() const;
- void setExtendedNamespace(const AbstractMetaClass *e);
+ AbstractMetaClassCPtr extendedNamespace() const;
+ void setExtendedNamespace(const AbstractMetaClassCPtr &e);
const AbstractMetaClassCList &innerClasses() const;
- void addInnerClass(AbstractMetaClass* cl);
+ void addInnerClass(const AbstractMetaClassPtr &cl);
void setInnerClasses(const AbstractMetaClassCList &innerClasses);
QString package() const;
bool isNamespace() const;
bool isInvisibleNamespace() const;
+ bool isInlineNamespace() const;
- bool isQObject() const { return inheritsFrom(u"QObject"_qs); }
bool isQtNamespace() const;
QString qualifiedCppName() const;
bool hasSignals() const;
- bool inheritsFrom(const AbstractMetaClass *other) const;
- bool inheritsFrom(const QString &name) const;
/**
* Says if the class that declares or inherits a virtual function.
@@ -240,16 +236,16 @@ public:
bool hasProtectedFields() const;
- const TypeEntries &templateArguments() const;
- void setTemplateArguments(const TypeEntries &);
+ const TypeEntryCList &templateArguments() const;
+ void setTemplateArguments(const TypeEntryCList &);
// only valid during metabuilder's run
const QStringList &baseClassNames() const;
void setBaseClassNames(const QStringList &names);
- const ComplexTypeEntry *typeEntry() const;
- ComplexTypeEntry *typeEntry();
- void setTypeEntry(ComplexTypeEntry *type);
+ ComplexTypeEntryCPtr typeEntry() const;
+ ComplexTypeEntryPtr typeEntry();
+ void setTypeEntry(const ComplexTypeEntryPtr &type);
/// Returns the global hash function as found by the code parser
QString hashFunction() const;
@@ -261,17 +257,19 @@ public:
const QList<QPropertySpec> &propertySpecs() const;
void addPropertySpec(const QPropertySpec &spec);
+ void setPropertyDocumentation(const QString &name, const Documentation &doc);
// Helpers to search whether a functions is a property setter/getter/reset
enum class PropertyFunction
{
Read,
Write,
- Reset
+ Reset,
+ Notify
};
struct PropertyFunctionSearchResult
{
- int index;
+ qsizetype index;
PropertyFunction function;
};
@@ -289,8 +287,8 @@ public:
void sortFunctions();
- const AbstractMetaClass *templateBaseClass() const;
- void setTemplateBaseClass(const AbstractMetaClass *cls);
+ AbstractMetaClassCPtr templateBaseClass() const;
+ void setTemplateBaseClass(const AbstractMetaClassCPtr &cls);
bool hasTemplateBaseClassInstantiations() const;
const AbstractMetaTypeList &templateBaseClassInstantiations() const;
@@ -314,18 +312,18 @@ public:
bool isCopyable() const;
bool isValueTypeWithCopyConstructorOnly() const;
void setValueTypeWithCopyConstructorOnly(bool v);
- static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClass *c,
+ static bool determineValueTypeWithCopyConstructorOnly(const AbstractMetaClassCPtr &c,
bool avoidProtectedHack);
- static AbstractMetaClass *findClass(const AbstractMetaClassList &classes,
- QStringView name);
- static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes,
- QStringView name);
- static AbstractMetaClass *findClass(const AbstractMetaClassList &classes,
- const TypeEntry* typeEntry);
- static const AbstractMetaClass *findClass(const AbstractMetaClassCList &classes,
- const TypeEntry* typeEntry);
- const AbstractMetaClass *findBaseClass(const QString &qualifiedName) const;
+ static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes,
+ QAnyStringView name);
+ static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes,
+ QAnyStringView name);
+ static AbstractMetaClassPtr findClass(const AbstractMetaClassList &classes,
+ const TypeEntryCPtr &typeEntry);
+ static AbstractMetaClassCPtr findClass(const AbstractMetaClassCList &classes,
+ const TypeEntryCPtr &typeEntry);
+ AbstractMetaClassCPtr findBaseClass(const QString &qualifiedName) const;
static std::optional<AbstractMetaEnumValue> findEnumValue(const AbstractMetaClassList &classes,
const QString &string);
@@ -334,7 +332,7 @@ public:
void setSourceLocation(const SourceLocation &sourceLocation);
// For AbstractMetaBuilder
- void fixFunctions();
+ static void fixFunctions(const AbstractMetaClassPtr &klass);
bool needsInheritanceSetup() const;
void setInheritanceDone(bool b);
bool inheritanceDone() const;
@@ -346,17 +344,15 @@ private:
#ifndef QT_NO_DEBUG_STREAM
void format(QDebug &d) const;
void formatMembers(QDebug &d) const;
+ friend QDebug operator<<(QDebug d, const AbstractMetaClassCPtr &ac);
+ friend QDebug operator<<(QDebug d, const AbstractMetaClassPtr &ac);
friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac);
+ friend void formatMetaClass(QDebug &, const AbstractMetaClass *);
#endif
QScopedPointer<AbstractMetaClassPrivate> d;
};
-inline bool AbstractMetaClass::isFinalInTargetLang() const
-{
- return attributes().testFlag(FinalInTargetLang);
-}
-
inline bool AbstractMetaClass::isAbstract() const
{
return attributes().testFlag(Abstract);
@@ -365,7 +361,7 @@ inline bool AbstractMetaClass::isAbstract() const
template <class Function>
void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const
{
- for (auto ic : innerClasses()) {
+ for (const auto &ic : innerClasses()) {
if (ic->isInvisibleNamespace()) {
f(ic);
ic->invisibleNamespaceRecursion(f);
@@ -373,6 +369,23 @@ void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const
}
}
+bool inheritsFrom(const AbstractMetaClassCPtr &c, const AbstractMetaClassCPtr &other);
+bool inheritsFrom(const AbstractMetaClassCPtr &c, QAnyStringView name);
+inline bool isQObject(const AbstractMetaClassCPtr &c)
+{
+ return inheritsFrom(c, "QObject");
+}
+
+AbstractMetaClassCPtr findBaseClass(const AbstractMetaClassCPtr &c,
+ const QString &qualifiedName);
+
+/// Return type entry of the base class that declares the parent management
+TypeEntryCPtr parentManagementEntry(const AbstractMetaClassCPtr &klass);
+inline bool hasParentManagement(const AbstractMetaClassCPtr &c)
+{ return bool(parentManagementEntry(c)); }
+
+AbstractMetaClassCList allBaseClasses(const AbstractMetaClassCPtr metaClass);
+
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::CppWrapper);
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::Attributes);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h
index 2bdfdb54d..9047c6bcd 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h
@@ -11,18 +11,15 @@ enum class FunctionQueryOption {
Constructors = 0x0000002, // Constructors except copy/move
CopyConstructor = 0x0000004, // Only copy constructors
//Destructors = 0x0000002, // Only destructors. Not included in class.
- FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang
ClassImplements = 0x0000020, // Only functions implemented by the current class
StaticFunctions = 0x0000080, // Only static functions
Signals = 0x0000100, // Only signals
NormalFunctions = 0x0000200, // Only functions that aren't signals
Visible = 0x0000400, // Only public and protected functions
- WasPublic = 0x0001000, // Only functions that were originally public
NonStaticFunctions = 0x0004000, // No static functions
Empty = 0x0008000, // Empty overrides of abstract functions
Invisible = 0x0010000, // Only private functions
VirtualInCppFunctions = 0x0020000, // Only functions that are virtual in C++
- VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang
NotRemoved = 0x0400000, // Only functions that have not been removed
OperatorOverloads = 0x2000000, // Only functions that are operator overloads
GenerateExceptionHandling = 0x4000000,
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h
index c1deea2c2..2a053ceaf 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang_helpers.h
@@ -4,21 +4,24 @@
#ifndef ABSTRACTMETALANG_HELPERS_H
#define ABSTRACTMETALANG_HELPERS_H
+#include "abstractmetalang_typedefs.h"
+
template <class MetaClass>
-MetaClass *findByName(QList<MetaClass *> haystack, QStringView needle)
+std::shared_ptr<MetaClass> findByName(const QList<std::shared_ptr<MetaClass> > &haystack,
+ QStringView needle)
{
- for (MetaClass *c : haystack) {
+ for (const auto &c : haystack) {
if (c->name() == needle)
return c;
}
- return nullptr;
+ return {};
}
// Helper for recursing the base classes of an AbstractMetaClass.
// Returns the class for which the predicate is true.
template <class Predicate>
-const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass,
- Predicate pred)
+AbstractMetaClassCPtr recurseClassHierarchy(const AbstractMetaClassCPtr &klass,
+ Predicate pred)
{
if (pred(klass))
return klass;
@@ -26,7 +29,7 @@ const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass,
if (auto r = recurseClassHierarchy(base, pred))
return r;
}
- return nullptr;
+ return {};
}
#endif // ABSTRACTMETALANG_HELPERS_H
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h
index 3b444197c..802f549cf 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang_typedefs.h
@@ -4,9 +4,10 @@
#ifndef ABSTRACTMETALANG_TYPEDEFS_H
#define ABSTRACTMETALANG_TYPEDEFS_H
-#include <QtCore/QSharedPointer>
#include <QtCore/QList>
+#include <memory>
+
class AbstractMetaClass;
class AbstractMetaField;
class AbstractMetaArgument;
@@ -16,12 +17,14 @@ class AbstractMetaFunction;
class AbstractMetaType;
struct UsingMember;
-using AbstractMetaFunctionPtr = QSharedPointer<AbstractMetaFunction>;
-using AbstractMetaFunctionCPtr = QSharedPointer<const AbstractMetaFunction>;
+using AbstractMetaFunctionPtr = std::shared_ptr<AbstractMetaFunction>;
+using AbstractMetaFunctionCPtr = std::shared_ptr<const AbstractMetaFunction>;
+using AbstractMetaClassPtr = std::shared_ptr<AbstractMetaClass>;
+using AbstractMetaClassCPtr = std::shared_ptr<const AbstractMetaClass>;
using AbstractMetaArgumentList = QList<AbstractMetaArgument>;
-using AbstractMetaClassList = QList<AbstractMetaClass *>;
-using AbstractMetaClassCList = QList<const AbstractMetaClass *>;
+using AbstractMetaClassList = QList<AbstractMetaClassPtr>;
+using AbstractMetaClassCList = QList<AbstractMetaClassCPtr>;
using AbstractMetaEnumList = QList<AbstractMetaEnum>;
using AbstractMetaEnumValueList = QList<AbstractMetaEnumValue>;
using AbstractMetaFieldList = QList<AbstractMetaField>;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
index a56557e76..3ec07509d 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
@@ -9,9 +9,9 @@
#include "containertypeentry.h"
#include "enumtypeentry.h"
#include "flagstypeentry.h"
-#include "parser/codemodel.h"
#include "qtcompat.h"
+#include "typeinfo.h"
#ifndef QT_NO_DEBUG_STREAM
# include <QtCore/QDebug>
@@ -19,12 +19,13 @@
#include <QtCore/QHash>
#include <QtCore/QSharedData>
-#include <QtCore/QSharedPointer>
#include <QtCore/QStack>
+#include <memory>
+
using namespace Qt::StringLiterals;
-using AbstractMetaTypeCPtr = QSharedPointer<const AbstractMetaType>;
+using AbstractMetaTypeCPtr = std::shared_ptr<const AbstractMetaType>;
const QSet<QString> &AbstractMetaType::cppFloatTypes()
{
@@ -107,7 +108,7 @@ const QSet<QString> &AbstractMetaType::cppPrimitiveTypes()
class AbstractMetaTypeData : public QSharedData
{
public:
- AbstractMetaTypeData(const TypeEntry *t);
+ AbstractMetaTypeData(const TypeEntryCPtr &t);
int actualIndirections() const;
bool passByConstRef() const;
@@ -118,11 +119,12 @@ public:
QString formatPythonSignature() const;
bool isEquivalent(const AbstractMetaTypeData &rhs) const;
bool equals(const AbstractMetaTypeData &rhs) const;
+ QStringList instantiationCppSignatures() const;
template <class Predicate>
bool generateOpaqueContainer(Predicate p) const;
- const TypeEntry *m_typeEntry;
+ TypeEntryCPtr m_typeEntry;
AbstractMetaTypeList m_instantiations;
mutable QString m_cachedCppSignature;
mutable QString m_cachedPythonSignature;
@@ -144,7 +146,7 @@ public:
AbstractMetaTypeList m_children;
};
-AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) :
+AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntryCPtr &t) :
m_typeEntry(t),
m_constant(false),
m_volatile(false),
@@ -153,7 +155,16 @@ AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) :
{
}
-AbstractMetaType::AbstractMetaType(const TypeEntry *t) : d(new AbstractMetaTypeData(t))
+QStringList AbstractMetaTypeData::instantiationCppSignatures() const
+{
+ QStringList result;
+ for (const auto &i : m_instantiations)
+ result.append(i.cppSignature());
+ return result;
+}
+
+AbstractMetaType::AbstractMetaType(const TypeEntryCPtr &t) :
+ d(new AbstractMetaTypeData(t))
{
Q_ASSERT(t);
}
@@ -167,9 +178,9 @@ AbstractMetaType &AbstractMetaType::operator=(const AbstractMetaType &) = defaul
AbstractMetaType::AbstractMetaType(const AbstractMetaType &rhs) = default;
-AbstractMetaType::AbstractMetaType(AbstractMetaType &&) = default;
+AbstractMetaType::AbstractMetaType(AbstractMetaType &&) noexcept = default;
-AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) = default;
+AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) noexcept = default;
AbstractMetaType::~AbstractMetaType() = default;
@@ -220,6 +231,11 @@ const AbstractMetaTypeList &AbstractMetaType::instantiations() const
return d->m_instantiations;
}
+QStringList AbstractMetaType::instantiationCppSignatures() const
+{
+ return d->instantiationCppSignatures();
+}
+
// For applying the <array> function argument modification: change into a type
// where "int *" becomes "int[]".
bool AbstractMetaType::applyArrayModification(QString *errorMessage)
@@ -229,7 +245,7 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage)
*errorMessage = u"<array> modification already applied."_s;
return false;
}
- if (!d->m_arrayElementType.isNull()) {
+ if (d->m_arrayElementType) {
QTextStream(errorMessage) << "The type \"" << cppSignature()
<< "\" is an array of " << d->m_arrayElementType->name() << '.';
return false;
@@ -253,12 +269,12 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage)
return true;
}
-const TypeEntry *AbstractMetaType::typeEntry() const
+TypeEntryCPtr AbstractMetaType::typeEntry() const
{
return d->m_typeEntry;
}
-void AbstractMetaType::setTypeEntry(const TypeEntry *type)
+void AbstractMetaType::setTypeEntry(const TypeEntryCPtr &type)
{
if (d->m_typeEntry != type)
d->m_typeEntry = type;
@@ -277,13 +293,13 @@ QString AbstractMetaType::originalTypeDescription() const
void AbstractMetaType::setOriginalTemplateType(const AbstractMetaType &type)
{
- if (d->m_originalTemplateType.isNull() || *d->m_originalTemplateType != type)
+ if (!d->m_originalTemplateType || *d->m_originalTemplateType != type)
d->m_originalTemplateType.reset(new AbstractMetaType(type));
}
const AbstractMetaType *AbstractMetaType::originalTemplateType() const
{
- return d->m_originalTemplateType.data();
+ return d->m_originalTemplateType.get();
}
AbstractMetaType AbstractMetaType::getSmartPointerInnerType() const
@@ -312,7 +328,7 @@ AbstractMetaTypeList AbstractMetaType::nestedArrayTypes() const
}
break;
case NativePointerAsArrayPattern:
- result.append(*d->m_arrayElementType.data());
+ result.append(*d->m_arrayElementType.get());
break;
default:
break;
@@ -340,6 +356,12 @@ bool AbstractMetaType::passByValue() const
return d->passByValue();
}
+bool AbstractMetaType::useStdMove() const
+{
+ return (isUniquePointer() && d->passByValue())
+ || d->m_referenceType == RValueReference;
+}
+
ReferenceType AbstractMetaType::referenceType() const
{
return d->m_referenceType;
@@ -418,17 +440,28 @@ int AbstractMetaType::arrayElementCount() const
const AbstractMetaType *AbstractMetaType::arrayElementType() const
{
- return d->m_arrayElementType.data();
+ return d->m_arrayElementType.get();
}
void AbstractMetaType::setArrayElementType(const AbstractMetaType &t)
{
- if (d->m_arrayElementType.isNull() || *d->m_arrayElementType != t) {
+ if (!d->m_arrayElementType || *d->m_arrayElementType != t) {
d->m_arrayElementType.reset(new AbstractMetaType(t));
d->m_signaturesDirty = true;
}
}
+AbstractMetaType AbstractMetaType::plainType() const
+{
+ AbstractMetaType result = *this;
+ result.clearIndirections();
+ result.setReferenceType(NoReference);
+ result.setConstant(false);
+ result.setVolatile(false);
+ result.decideUsagePattern();
+ return result;
+}
+
QString AbstractMetaType::cppSignature() const
{
const AbstractMetaTypeData *cd = d.constData();
@@ -510,6 +543,7 @@ void AbstractMetaType::decideUsagePattern()
pattern = ObjectPattern;
}
setTypeUsagePattern(pattern);
+ Q_ASSERT(pattern != ContainerPattern || !d->m_instantiations.isEmpty());
}
bool AbstractMetaTypeData::hasTemplateChildren() const
@@ -543,6 +577,29 @@ static inline QString formatArraySize(int e)
return result;
}
+// Return the number of template parameters; remove the default
+// non template type parameter of std::span from the signature.
+static qsizetype stripDefaultTemplateArgs(const TypeEntryCPtr &te,
+ const AbstractMetaTypeList &instantiations)
+{
+ static const char16_t dynamicExtent64[] = u"18446744073709551615"; // size_t(-1)
+ static const char16_t dynamicExtent32[] = u"4294967295";
+
+ qsizetype result = instantiations.size();
+ if (result == 0 || !te->isContainer())
+ return result;
+ auto cte = std::static_pointer_cast<const ContainerTypeEntry>(te);
+ if (cte->containerKind() != ContainerTypeEntry::SpanContainer)
+ return result;
+ const auto lastTe = instantiations.constLast().typeEntry();
+ if (lastTe->type() == TypeEntry::ConstantValueType) {
+ const QString &name = lastTe->name();
+ if (name == dynamicExtent64 || name == dynamicExtent32)
+ --result;
+ }
+ return result;
+}
+
QString AbstractMetaTypeData::formatSignature(bool minimal) const
{
QString result;
@@ -565,12 +622,13 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const
result += u'<';
if (minimal)
result += u' ';
- for (int i = 0, size = m_instantiations.size(); i < size; ++i) {
+ const auto size = stripDefaultTemplateArgs(m_typeEntry, m_instantiations);
+ for (qsizetype i = 0; i < size; ++i) {
if (i > 0)
result += u',';
result += m_instantiations.at(i).minimalSignature();
}
- result += u" >"_s;
+ result += u'>';
}
if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference))
@@ -633,7 +691,7 @@ QString AbstractMetaTypeData::formatPythonSignature() const
}
if (!m_instantiations.isEmpty()) {
result += u'[';
- for (int i = 0, size = m_instantiations.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) {
if (i > 0)
result += u", "_s;
result += m_instantiations.at(i).formatPythonSignature();
@@ -643,18 +701,12 @@ QString AbstractMetaTypeData::formatPythonSignature() const
if (m_typeEntry->isPrimitive())
for (Indirection i : m_indirections)
result += TypeInfo::indirectionKeyword(i);
- // If it is a flags type, we replace it with the full name:
- // "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>"
+ // If it is a flags type, we replace it with the full name of the enum:
+ // "PySide6.QtCore.Qt.ItemFlag" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>"
if (m_typeEntry->isFlags()) {
- // PYSIDE-1735: We need to provide both the flags type and the original enum type
- // as a choice at runtime.
- auto flagsTypeEntry = static_cast<const FlagsTypeEntry *>(m_typeEntry);
- auto enumTypeEntry = flagsTypeEntry->originator();
- result = m_typeEntry->targetLangPackage() + u".^^"_s
- + flagsTypeEntry->targetLangName() + u"^^"_s
- + enumTypeEntry->targetLangName() + u"^^"_s;
+ const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(m_typeEntry);
+ result = fte->originator()->qualifiedTargetLangName();
}
-
result.replace(u"::"_s, u"."_s);
return result;
}
@@ -666,7 +718,7 @@ QString AbstractMetaType::formatPythonSignature() const
bool AbstractMetaType::isCppPrimitive() const
{
- return d->m_pattern == PrimitivePattern && d->m_typeEntry->isCppPrimitive();
+ return d->m_pattern == PrimitivePattern && ::isCppPrimitive(d->m_typeEntry);
}
bool AbstractMetaType::isConstant() const
@@ -697,9 +749,9 @@ void AbstractMetaType::setVolatile(bool v)
static bool equalsCPtr(const AbstractMetaTypeCPtr &t1, const AbstractMetaTypeCPtr &t2)
{
- if (t1.isNull() != t2.isNull())
+ if (bool(t1) != bool(t2))
return false;
- return t1.isNull() || *t1 == *t2;
+ return !t1 || *t1 == *t2;
}
bool AbstractMetaTypeData::isEquivalent(const AbstractMetaTypeData &rhs) const
@@ -727,9 +779,9 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const
&& m_referenceType == rhs.m_referenceType && isEquivalent(rhs);
}
-bool AbstractMetaType::equals(const AbstractMetaType &rhs) const
+bool comparesEqual(const AbstractMetaType &lhs, const AbstractMetaType &rhs) noexcept
{
- return d->equals(*rhs.d);
+ return lhs.d->equals(*rhs.d);
}
bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const
@@ -739,12 +791,12 @@ bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const
const AbstractMetaType *AbstractMetaType::viewOn() const
{
- return d->m_viewOn.data();
+ return d->m_viewOn.get();
}
void AbstractMetaType::setViewOn(const AbstractMetaType &v)
{
- if (d->m_viewOn.isNull() || *d->m_viewOn != v)
+ if (!d->m_viewOn || *d->m_viewOn != v)
d->m_viewOn.reset(new AbstractMetaType(v));
}
@@ -752,7 +804,7 @@ AbstractMetaType AbstractMetaType::createVoid()
{
static QScopedPointer<AbstractMetaType> metaType;
if (metaType.isNull()) {
- static const TypeEntry *voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s);
+ static TypeEntryCPtr voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s);
Q_ASSERT(voidTypeEntry);
metaType.reset(new AbstractMetaType(voidTypeEntry));
metaType->decideUsagePattern();
@@ -766,13 +818,18 @@ void AbstractMetaType::dereference(QString *type)
type->append(u')');
}
+QString AbstractMetaType::dereferencePrefix(qsizetype n)
+{
+ const QChar c = n > 0 ? u'*' : u'&';
+ return QString(qAbs(n), c);
+}
+
void AbstractMetaType::applyDereference(QString *type, qsizetype n)
{
if (n == 0)
return;
- const char c = n > 0 ? '*' : '&';
- type->prepend(QString(qAbs(n), QLatin1Char(c)));
+ type->prepend(dereferencePrefix(n));
type->prepend(u'(');
type->append(u')');
}
@@ -832,7 +889,7 @@ bool AbstractMetaType::isVoidPointer() const
bool AbstractMetaType::isUserPrimitive() const
{
- return d->m_indirections.isEmpty() && d->m_typeEntry->isUserPrimitive();
+ return d->m_indirections.isEmpty() && ::isUserPrimitive(d->m_typeEntry);
}
bool AbstractMetaType::isObjectTypeUsedAsValueType() const
@@ -857,28 +914,9 @@ bool AbstractMetaType::isWrapperPassedByReference() const
&& !isPointer();
}
-qsizetype AbstractMetaType::shouldDereferenceArgument() const
-{
- if (isWrapperPassedByReference() || valueTypeWithCopyConstructorOnlyPassed()
- || isObjectTypeUsedAsValueType()) {
- return 1;
- }
-
- if (!d->m_typeEntry->isContainer())
- return 0;
-
- qsizetype result = -d->m_indirections.size();
-
- // For opaque containers, the cppArg in the generated code is a pointer
- if (generateOpaqueContainer())
- ++result;
-
- return result;
-}
-
bool AbstractMetaType::isCppIntegralPrimitive() const
{
- return d->m_typeEntry->isCppIntegralPrimitive();
+ return ::isCppIntegralPrimitive(d->m_typeEntry);
}
bool AbstractMetaType::isExtendedCppPrimitive() const
@@ -887,14 +925,14 @@ bool AbstractMetaType::isExtendedCppPrimitive() const
return true;
if (!d->m_indirections.isEmpty())
return false;
- return d->m_typeEntry->isExtendedCppPrimitive();
+ return ::isExtendedCppPrimitive(d->m_typeEntry);
}
bool AbstractMetaType::isValueTypeWithCopyConstructorOnly() const
{
bool result = false;
if (d->m_typeEntry->isComplex()) {
- const auto *cte = static_cast<const ComplexTypeEntry *>(d->m_typeEntry);
+ const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(d->m_typeEntry);
result = cte->isValueTypeWithCopyConstructorOnly();
}
return result;
@@ -911,14 +949,18 @@ using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>;
Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache)
std::optional<AbstractMetaType>
-AbstractMetaType::fromString(QString typeSignature, QString *errorMessage)
+AbstractMetaType::fromString(const QString &typeSignatureIn, QString *errorMessage)
{
- typeSignature = typeSignature.trimmed();
+ auto &cache = *metaTypeFromStringCache();
+ auto it = cache.find(typeSignatureIn);
+ if (it != cache.end())
+ return it.value();
+
+ QString typeSignature = typeSignatureIn.trimmed();
if (typeSignature.startsWith(u"::"))
typeSignature.remove(0, 2);
- auto &cache = *metaTypeFromStringCache();
- auto it = cache.find(typeSignature);
+ it = cache.find(typeSignature);
if (it == cache.end()) {
auto metaType =
AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage);
@@ -927,12 +969,14 @@ AbstractMetaType::fromString(QString typeSignature, QString *errorMessage)
errorMessage->prepend(msgCannotBuildMetaType(typeSignature));
return {};
}
+ if (typeSignature != typeSignatureIn)
+ cache.insert(typeSignatureIn, metaType.value());
it = cache.insert(typeSignature, metaType.value());
}
return it.value();
}
-AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry)
+AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntryCPtr &typeEntry)
{
QString typeName = typeEntry->qualifiedCppName();
if (typeName.startsWith(u"::"))
@@ -941,16 +985,12 @@ AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry)
auto it = cache.find(typeName);
if (it != cache.end())
return it.value();
- AbstractMetaType metaType(typeEntry);
- metaType.clearIndirections();
- metaType.setReferenceType(NoReference);
- metaType.setConstant(false);
- metaType.decideUsagePattern();
+ AbstractMetaType metaType = AbstractMetaType(typeEntry).plainType();
cache.insert(typeName, metaType);
return metaType;
}
-AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClass *metaClass)
+AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass)
{
return fromTypeEntry(metaClass->typeEntry());
}
@@ -963,37 +1003,34 @@ bool AbstractMetaTypeData::generateOpaqueContainer(Predicate pred) const
return false;
if (m_indirections.size() > 1)
return false;
- auto *containerTypeEntry = static_cast<const ContainerTypeEntry *>(m_typeEntry);
+ auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(m_typeEntry);
auto kind = containerTypeEntry->containerKind();
- if (kind != ContainerTypeEntry::ListContainer)
- return false;
- const auto &instantation = m_instantiations.constFirst();
- if (instantation.referenceType() != NoReference)
+ if (kind != ContainerTypeEntry::ListContainer && kind != ContainerTypeEntry::SpanContainer)
return false;
- const QString signature = instantation.cppSignature();
- bool result = false;
- auto *instTypEntry = instantation.typeEntry();
- switch (instTypEntry->type()) {
+ const auto &firstInstantiation = m_instantiations.constFirst();
+ if (firstInstantiation.referenceType() != NoReference)
+ return false;
+ switch (firstInstantiation.typeEntry()->type()) {
case TypeEntry::PrimitiveType:
case TypeEntry::FlagsType:
case TypeEntry::EnumType:
case TypeEntry::BasicValueType:
case TypeEntry::ObjectType:
case TypeEntry::CustomType:
- result = pred(containerTypeEntry, signature);
break;
default:
- break;
+ return false;
}
- return result;
+
+ return pred(containerTypeEntry, instantiationCppSignatures());
}
// Simple predicate for checking whether an opaque container should be generated
-static bool opaqueContainerPredicate(const ContainerTypeEntry *t,
- const QString &signature)
+static bool opaqueContainerPredicate(const ContainerTypeEntryCPtr &t,
+ const QStringList &instantiations)
{
- return t->generateOpaqueContainer(signature);
+ return t->generateOpaqueContainer(instantiations);
}
bool AbstractMetaType::generateOpaqueContainer() const
@@ -1006,8 +1043,9 @@ bool AbstractMetaType::generateOpaqueContainer() const
// (cf AbstractMetaFunction::generateOpaqueContainerReturn())
bool AbstractMetaType::generateOpaqueContainerForGetter(const QString &modifiedType) const
{
- auto predicate = [&modifiedType](const ContainerTypeEntry *t, const QString &signature) {
- return t->opaqueContainerName(signature) == modifiedType;
+ auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t,
+ const QStringList &instantiations) {
+ return t->opaqueContainerName(instantiations) == modifiedType;
};
return d->generateOpaqueContainer(predicate);
}
@@ -1031,7 +1069,7 @@ void AbstractMetaType::formatDebug(QDebug &debug) const
for (auto i : indirections)
debug << ' ' << TypeInfo::indirectionKeyword(i);
}
- if (referenceType())
+ if (referenceType() != NoReference)
debug << ", reftype=" << referenceType();
if (isConstant())
debug << ", [const]";
@@ -1042,9 +1080,9 @@ void AbstractMetaType::formatDebug(QDebug &debug) const
<< "\", arrayElementCount=" << arrayElementCount();
}
const auto &instantiations = this->instantiations();
- if (const int instantiationsSize = instantiations.size()) {
+ if (const auto instantiationsSize = instantiations.size()) {
debug << ", instantiations[" << instantiationsSize << "]=<";
- for (int i = 0; i < instantiationsSize; ++i) {
+ for (qsizetype i = 0; i < instantiationsSize; ++i) {
if (i)
debug << ", ";
instantiations.at(i).formatDebug(debug);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.h b/sources/shiboken6/ApiExtractor/abstractmetatype.h
index 561cac317..8a1ecdf20 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetatype.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetatype.h
@@ -7,8 +7,11 @@
#include "abstractmetalang_enums.h"
#include "abstractmetalang_typedefs.h"
#include "parser/codemodel_enums.h"
+#include "typedatabase_typedefs.h"
+#include <QtCore/QtCompare>
#include <QtCore/qobjectdefs.h>
+#include <QtCore/QHashFunctions>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QList>
#include <QtCore/QSet>
@@ -46,11 +49,11 @@ public:
Q_ENUM(TypeUsagePattern)
AbstractMetaType();
- explicit AbstractMetaType(const TypeEntry *t);
+ explicit AbstractMetaType(const TypeEntryCPtr &t);
AbstractMetaType(const AbstractMetaType &);
AbstractMetaType &operator=(const AbstractMetaType &);
- AbstractMetaType(AbstractMetaType &&);
- AbstractMetaType &operator=(AbstractMetaType &&);
+ AbstractMetaType(AbstractMetaType &&) noexcept;
+ AbstractMetaType &operator=(AbstractMetaType &&) noexcept;
~AbstractMetaType();
QString package() const;
@@ -66,6 +69,7 @@ public:
const AbstractMetaTypeList &instantiations() const;
void addInstantiation(const AbstractMetaType &inst);
void setInstantiations(const AbstractMetaTypeList &insts);
+ QStringList instantiationCppSignatures() const;
QString minimalSignature() const { return formatSignature(true); }
@@ -117,6 +121,7 @@ public:
bool passByConstRef() const;
bool passByValue() const;
+ bool useStdMove() const;
ReferenceType referenceType() const;
void setReferenceType(ReferenceType ref);
@@ -140,14 +145,17 @@ public:
AbstractMetaTypeList nestedArrayTypes() const;
+ /// Strip const/indirections/reference from the type
+ AbstractMetaType plainType() const;
+
QString cppSignature() const;
QString pythonSignature() const;
bool applyArrayModification(QString *errorMessage);
- const TypeEntry *typeEntry() const;
- void setTypeEntry(const TypeEntry *type);
+ TypeEntryCPtr typeEntry() const;
+ void setTypeEntry(const TypeEntryCPtr &type);
void setOriginalTypeDescription(const QString &otd);
QString originalTypeDescription() const;
@@ -164,7 +172,6 @@ public:
bool hasTemplateChildren() const;
- bool equals(const AbstractMetaType &rhs) const;
/// Is equivalent from the POV of argument passing (differ by const ref)
bool isEquivalent(const AbstractMetaType &rhs) const;
@@ -181,14 +188,15 @@ public:
/// \param typeSignature The string describing the type to be built.
/// \return A new AbstractMetaType object or nullopt in case of failure.
static std::optional<AbstractMetaType>
- fromString(QString typeSignature, QString *errorMessage = nullptr);
+ fromString(const QString &typeSignatureIn, QString *errorMessage = nullptr);
/// Creates an AbstractMetaType object from a TypeEntry.
- static AbstractMetaType fromTypeEntry(const TypeEntry *typeEntry);
+ static AbstractMetaType fromTypeEntry(const TypeEntryCPtr &typeEntry);
/// Creates an AbstractMetaType object from an AbstractMetaClass.
- static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClass *metaClass);
+ static AbstractMetaType fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass);
static void dereference(QString *type); // "foo" -> "(*foo)"
/// Apply the result of shouldDereferenceArgument()
+ static QString dereferencePrefix(qsizetype n); // Return the prefix **/& as as required
static void applyDereference(QString *type, qsizetype n);
static bool stripDereference(QString *type); // "(*foo)" -> "foo"
@@ -214,10 +222,6 @@ public:
bool isPointerToWrapperType() const;
/// Wrapper type passed by reference
bool isWrapperPassedByReference() const;
- /// Checks if the meta type of an argument should be dereferenced by the Python
- /// method wrapper passing it to C++.
- /// \return positive numbers for dereferencing, negative for referencing
- qsizetype shouldDereferenceArgument() const;
/// Returns true if the type is a C++ integral primitive,
/// i.e. bool, char, int, long, and their unsigned counterparts.
bool isCppIntegralPrimitive() const;
@@ -250,6 +254,12 @@ public:
#endif
private:
+ friend size_t qHash(const AbstractMetaType &t, size_t seed = 0) noexcept
+ { return qHash(t.typeEntry().get(), seed); }
+ friend bool comparesEqual(const AbstractMetaType &lhs,
+ const AbstractMetaType &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(AbstractMetaType)
+
friend class AbstractMetaTypeData;
QSharedDataPointer<AbstractMetaTypeData> d;
@@ -258,14 +268,6 @@ private:
QString formatPythonSignature() const;
};
-inline bool operator==(const AbstractMetaType &t1, const AbstractMetaType &t2)
-{ return t1.equals(t2); }
-inline bool operator!=(const AbstractMetaType &t1, const AbstractMetaType &t2)
-{ return !t1.equals(t2); }
-
-inline size_t qHash(const AbstractMetaType &t, size_t seed)
-{ return qHash(t.typeEntry(), seed); }
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const AbstractMetaType &at);
QDebug operator<<(QDebug d, const AbstractMetaType *at);
diff --git a/sources/shiboken6/ApiExtractor/addedfunction.cpp b/sources/shiboken6/ApiExtractor/addedfunction.cpp
new file mode 100644
index 000000000..9d95b734c
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/addedfunction.cpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "addedfunction.h"
+#include "addedfunction_p.h"
+#include "typeparser.h"
+
+#include <QtCore/QDebug>
+
+using namespace Qt::StringLiterals;
+
+constexpr auto callOperator = "operator()"_L1;
+
+// Helpers to split a parameter list of <add-function>, <declare-function>
+// (@ denoting names), like
+// "void foo(QList<X,Y> &@list@ = QList<X,Y>{1,2}, int @b@=5, ...)"
+namespace AddedFunctionParser {
+
+QDebug operator<<(QDebug d, const Argument &a)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "Argument(type=\"" << a.type << '"';
+ if (!a.name.isEmpty())
+ d << ", name=\"" << a.name << '"';
+ if (!a.defaultValue.isEmpty())
+ d << ", defaultValue=\"" << a.defaultValue << '"';
+ d << ')';
+ return d;
+}
+
+// Helper for finding the end of a function parameter, observing
+// nested template parameters or lists.
+static qsizetype parameterTokenEnd(qsizetype startPos, QStringView paramString)
+{
+ const auto end = paramString.size();
+ int nestingLevel = 0;
+ for (qsizetype p = startPos; p < end; ++p) {
+ switch (paramString.at(p).toLatin1()) {
+ case ',':
+ if (nestingLevel == 0)
+ return p;
+ break;
+ case '<': // templates
+ case '{': // initializer lists of default values
+ case '(': // initialization, function pointers
+ case '[': // array dimensions
+ ++nestingLevel;
+ break;
+ case '>':
+ case '}':
+ case ')':
+ case ']':
+ --nestingLevel;
+ break;
+ }
+ }
+ return end;
+}
+
+// Split a function parameter list into string tokens containing one
+// parameters (including default value, etc).
+static QList<QStringView> splitParameterTokens(QStringView paramString)
+{
+ QList<QStringView> result;
+ qsizetype startPos = 0;
+ for ( ; startPos < paramString.size(); ) {
+ const auto end = parameterTokenEnd(startPos, paramString);
+ result.append(paramString.mid(startPos, end - startPos).trimmed());
+ startPos = end + 1;
+ }
+ return result;
+}
+
+// Split a function parameter list
+Arguments splitParameters(QStringView paramString, QString *errorMessage)
+{
+ Arguments result;
+ const QList<QStringView> tokens = splitParameterTokens(paramString);
+
+ for (const auto &t : tokens) {
+ Argument argument;
+ // Check defaultValue, "int @b@=5"
+ const auto equalPos = t.lastIndexOf(u'=');
+ if (equalPos != -1) {
+ const int defaultValuePos = equalPos + 1;
+ argument.defaultValue =
+ t.mid(defaultValuePos, t.size() - defaultValuePos).trimmed().toString();
+ }
+ QString typeString = (equalPos != -1 ? t.left(equalPos) : t).trimmed().toString();
+ // Check @name@
+ const auto atPos = typeString.indexOf(u'@');
+ if (atPos != -1) {
+ const int namePos = atPos + 1;
+ const int nameEndPos = typeString.indexOf(u'@', namePos);
+ if (nameEndPos == -1) {
+ if (errorMessage != nullptr) {
+ *errorMessage = u"Mismatched @ in \""_s
+ + paramString.toString() + u'"';
+ }
+ return {};
+ }
+ argument.name = typeString.mid(namePos, nameEndPos - namePos).trimmed();
+ typeString.remove(atPos, nameEndPos - atPos + 1);
+ }
+ argument.type = typeString.trimmed();
+ result.append(argument);
+ }
+
+ return result;
+}
+
+} // namespace AddedFunctionParser
+
+AddedFunction::AddedFunction(const QString &name, const QList<Argument> &arguments,
+ const TypeInfo &returnType) :
+ m_name(name),
+ m_arguments(arguments),
+ m_returnType(returnType)
+{
+}
+
+AddedFunction::AddedFunctionPtr
+ AddedFunction::createAddedFunction(const QString &signatureIn, const QString &returnTypeIn,
+ QString *errorMessage)
+
+{
+ errorMessage->clear();
+
+ QList<Argument> arguments;
+ const TypeInfo returnType = returnTypeIn.isEmpty()
+ ? TypeInfo::voidType()
+ : TypeParser::parse(returnTypeIn, errorMessage);
+ if (!errorMessage->isEmpty())
+ return {};
+
+ QStringView signature = QStringView{signatureIn}.trimmed();
+
+ // Skip past "operator()(...)"
+ const auto parenSearchStartPos = signature.startsWith(callOperator)
+ ? callOperator.size() : 0;
+ const auto openParenPos = signature.indexOf(u'(', parenSearchStartPos);
+ if (openParenPos < 0) {
+ return AddedFunctionPtr(new AddedFunction(signature.toString(),
+ arguments, returnType));
+ }
+
+ const QString name = signature.left(openParenPos).trimmed().toString();
+ const auto closingParenPos = signature.lastIndexOf(u')');
+ if (closingParenPos < 0) {
+ *errorMessage = u"Missing closing parenthesis"_s;
+ return {};
+ }
+
+ // Check for "foo() const"
+ bool isConst = false;
+ const auto signatureLength = signature.length();
+ const auto qualifierLength = signatureLength - closingParenPos - 1;
+ if (qualifierLength >= 5
+ && signature.right(qualifierLength).contains(u"const")) {
+ isConst = true;
+ }
+
+ const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1);
+ const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage);
+ if (params.isEmpty() && !errorMessage->isEmpty())
+ return {};
+ for (const auto &p : params) {
+ TypeInfo type = p.type == u"..."
+ ? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage);
+ if (!errorMessage->isEmpty()) {
+ errorMessage->prepend(u"Unable to parse added function "_s + signatureIn
+ + u": "_s);
+ return {};
+ }
+ arguments.append({type, p.name, p.defaultValue});
+ }
+
+ auto result = std::make_shared<AddedFunction>(name, arguments, returnType);
+ result->setConstant(isConst);
+ return result;
+}
+
+QDebug operator<<(QDebug d, const AddedFunction::Argument &a)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "Argument(";
+ d << a.typeInfo;
+ if (!a.name.isEmpty())
+ d << ' ' << a.name;
+ if (!a.defaultValue.isEmpty())
+ d << " = " << a.defaultValue;
+ d << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const AddedFunction &af)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AddedFunction(";
+ if (af.access() == AddedFunction::Protected)
+ d << "protected";
+ if (af.isStatic())
+ d << " static";
+ d << af.returnType() << ' ' << af.name() << '(' << af.arguments() << ')';
+ if (af.isConstant())
+ d << " const";
+ if (af.isDeclaration())
+ d << " [declaration]";
+ return d;
+}
diff --git a/sources/shiboken6/ApiExtractor/addedfunction.h b/sources/shiboken6/ApiExtractor/addedfunction.h
new file mode 100644
index 000000000..b8d189b7a
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/addedfunction.h
@@ -0,0 +1,113 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef ADDEDFUNCTION_H
+#define ADDEDFUNCTION_H
+
+#include "modifications.h"
+#include "parser/typeinfo.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+#include <memory>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+/// \internal
+/// Struct used to store information about functions added by the typesystem.
+/// This info will be used later to create a fake AbstractMetaFunction which
+/// will be inserted into the right AbstractMetaClass.
+struct AddedFunction
+{
+ using AddedFunctionPtr = std::shared_ptr<AddedFunction>;
+
+ /// Function access types.
+ enum Access {
+ Protected = 0x1,
+ Public = 0x2
+ };
+
+ struct Argument
+ {
+ TypeInfo typeInfo;
+ QString name;
+ QString defaultValue;
+ };
+
+ /// Creates a new AddedFunction with a signature and a return type.
+ explicit AddedFunction(const QString &name, const QList<Argument> &arguments,
+ const TypeInfo &returnType);
+
+ static AddedFunctionPtr createAddedFunction(const QString &signatureIn,
+ const QString &returnTypeIn,
+ QString *errorMessage);
+
+ AddedFunction() = default;
+
+ /// Returns the function name.
+ QString name() const { return m_name; }
+
+ /// Set the function access type.
+ void setAccess(Access access) { m_access = access; }
+
+ /// Returns the function access type.
+ Access access() const { return m_access; }
+
+ /// Returns the function return type.
+ const TypeInfo &returnType() const { return m_returnType; }
+
+ /// Returns a list of argument type infos.
+ const QList<Argument> &arguments() const { return m_arguments; }
+
+ /// Returns true if this is a constant method.
+ bool isConstant() const { return m_isConst; }
+ void setConstant(bool c) { m_isConst = c; };
+
+ /// Set this method static.
+ void setStatic(bool value) { m_isStatic = value; }
+
+ /// Set this method as a classmethod.
+ void setClassMethod(bool value) { m_isClassMethod = value; }
+
+ /// Returns true if this is a static method.
+ bool isStatic() const { return m_isStatic; }
+
+ /// Returns true if this is a class method.
+ bool isClassMethod() const { return m_isClassMethod; }
+
+ bool isDeclaration() const { return m_isDeclaration; } // <declare-function>
+ void setDeclaration(bool value) { m_isDeclaration = value; }
+
+ bool isPythonOverride() const { return m_isPythonOverride; }
+ void setPythonOverride(bool o) { m_isPythonOverride = o; }
+
+ const FunctionModificationList &modifications() const { return m_modifications; }
+ FunctionModificationList &modifications() { return m_modifications; }
+
+ const DocModificationList &docModifications() const { return m_docModifications; }
+ DocModificationList &docModifications() { return m_docModifications; }
+ void addDocModification(const DocModification &m) { m_docModifications.append(m); }
+
+ QString targetLangPackage() const { return m_targetLangPackage; }
+ void setTargetLangPackage(const QString &p) { m_targetLangPackage = p; }
+
+private:
+ QString m_name;
+ QList<Argument> m_arguments;
+ TypeInfo m_returnType;
+ FunctionModificationList m_modifications;
+ DocModificationList m_docModifications;
+ QString m_targetLangPackage;
+ Access m_access = Public;
+ bool m_isConst = false;
+ bool m_isClassMethod = false;
+ bool m_isStatic = false;
+ bool m_isDeclaration = false;
+ bool m_isPythonOverride = false;
+};
+
+QDebug operator<<(QDebug d, const AddedFunction::Argument &a);
+QDebug operator<<(QDebug d, const AddedFunction &af);
+
+#endif // ADDEDFUNCTION_H
diff --git a/sources/shiboken6/ApiExtractor/modifications_p.h b/sources/shiboken6/ApiExtractor/addedfunction_p.h
index e21df9061..40b69a5df 100644
--- a/sources/shiboken6/ApiExtractor/modifications_p.h
+++ b/sources/shiboken6/ApiExtractor/addedfunction_p.h
@@ -1,9 +1,10 @@
-// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#ifndef MODIFICATIONS_P_H
-#define MODIFICATIONS_P_H
+#ifndef ADDEDFUNCTION_P_H
+#define ADDEDFUNCTION_P_H
+#include <QtCore/QtCompare>
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QStringView>
@@ -19,18 +20,20 @@ namespace AddedFunctionParser {
struct Argument
{
- bool equals(const Argument &rhs) const;
-
QString type;
QString name;
QString defaultValue;
+
+ friend bool comparesEqual(const Argument &lhs, const Argument &rhs) noexcept
+ {
+ return lhs.type == rhs.type && lhs.name == rhs.name
+ && lhs.defaultValue == rhs.defaultValue;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(Argument)
};
using Arguments = QList<Argument>;
-inline bool operator==(const Argument &a1, const Argument &a2) { return a1.equals(a2); }
-inline bool operator!=(const Argument &a1, const Argument &a2) { return !a1.equals(a2); }
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const Argument &a);
#endif
diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp
new file mode 100644
index 000000000..35d2d535a
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "anystringview_helpers.h"
+
+#include <QtCore/QString> // Must go before QAnyStringView for operator<<(QTextStream,QASV)!
+#include <QtCore/QAnyStringView>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+#include <cstring>
+
+QTextStream &operator<<(QTextStream &str, QAnyStringView asv)
+{
+ asv.visit([&str](auto s) { str << s; });
+ return str;
+}
+
+static bool asv_containsImpl(QLatin1StringView v, char c)
+{
+ return v.contains(uint16_t(c));
+}
+
+static bool asv_containsImpl(QUtf8StringView v, char c)
+{
+ return std::strchr(v.data(), c) != nullptr;
+}
+
+static bool asv_containsImpl(QStringView v, char c)
+{
+ return v.contains(uint16_t(c));
+}
+
+bool asv_contains(QAnyStringView asv, char needle)
+{
+ return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); });
+}
+
+static bool asv_containsImpl(QLatin1StringView v, const char *c)
+{
+ return v.contains(QLatin1StringView(c));
+}
+static bool asv_containsImpl(QUtf8StringView v, const char *c)
+{
+ return std::strstr(v.data(), c) != nullptr;
+}
+
+static bool asv_containsImpl(QStringView v, const char *c)
+{
+ return v.contains(QLatin1StringView(c));
+}
+
+bool asv_contains(QAnyStringView asv, const char *needle)
+{
+ return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); });
+}
diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.h b/sources/shiboken6/ApiExtractor/anystringview_helpers.h
new file mode 100644
index 000000000..e1e6ab7f0
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef ANYSTRINGVIEW_STREAM_H
+#define ANYSTRINGVIEW_STREAM_H
+
+#include <QtCore/QtClassHelperMacros>
+
+QT_FORWARD_DECLARE_CLASS(QAnyStringView)
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+QTextStream &operator<<(QTextStream &str, QAnyStringView asv);
+
+bool asv_contains(QAnyStringView asv, char needle);
+bool asv_contains(QAnyStringView asv, const char *needle);
+
+#endif // ANYSTRINGVIEW_STREAM_H
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp
index d18758fe8..83ee4437e 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp
@@ -3,7 +3,6 @@
#include "apiextractor.h"
#include "apiextractorresult.h"
-#include "apiextractorresultdata_p.h"
#include "abstractmetaargument.h"
#include "abstractmetabuilder.h"
#include "abstractmetaenum.h"
@@ -12,8 +11,9 @@
#include "abstractmetalang.h"
#include "codesnip.h"
#include "exception.h"
-#include "fileout.h"
+#include "messages.h"
#include "modifications.h"
+#include "optionsparser.h"
#include "reporthandler.h"
#include "typedatabase.h"
#include "customconversion.h"
@@ -21,6 +21,7 @@
#include "primitivetypeentry.h"
#include "smartpointertypeentry.h"
#include "typedefentry.h"
+#include "namespacetypeentry.h"
#include "typesystemtypeentry.h"
#include "qtcompat.h"
@@ -40,136 +41,250 @@ struct InstantiationCollectContext
AbstractMetaTypeList instantiatedContainers;
InstantiatedSmartPointers instantiatedSmartPointers;
QStringList instantiatedContainersNames;
- QList<const TypeEntry *> m_synthesizedTypeEntries;
};
-struct ApiExtractorPrivate
+struct ApiExtractorOptions
{
- bool runHelper(ApiExtractorFlags flags);
-
- static QString getSimplifiedContainerTypeName(const AbstractMetaType &type);
- void addInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
- const AbstractMetaType &type,
- const QString &contextName);
- void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
- const AbstractMetaFunctionCPtr &func);
- void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
- const AbstractMetaClass *metaClass);
- void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context);
- void collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context);
- void collectContainerTypesFromSnippets(InstantiationCollectContext &context);
- void collectContainerTypesFromConverterMacros(InstantiationCollectContext &context,
- const QString &code,
- bool toPythonMacro);
- void addInstantiatedSmartPointer(InstantiationCollectContext &context,
- const AbstractMetaType &type);
-
QString m_typeSystemFileName;
QFileInfoList m_cppFileNames;
HeaderPaths m_includePaths;
QStringList m_clangOptions;
- AbstractMetaBuilder* m_builder = nullptr;
QString m_logDirectory;
LanguageLevel m_languageLevel = LanguageLevel::Default;
bool m_skipDeprecated = false;
};
-ApiExtractor::ApiExtractor() :
- d(new ApiExtractorPrivate)
+static inline QString languageLevelDescription()
{
- // Environment TYPESYSTEMPATH
- QString envTypesystemPaths = QFile::decodeName(qgetenv("TYPESYSTEMPATH"));
- if (!envTypesystemPaths.isEmpty())
- TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths);
+ return u"C++ Language level (c++11..c++17, default="_s
+ + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ + u')';
}
-ApiExtractor::~ApiExtractor()
+QList<OptionDescription> ApiExtractor::options()
{
- delete d->m_builder;
- delete d;
+ return {
+ {u"use-global-header"_s,
+ u"Use the global headers in generated code."_s},
+ {u"clang-option"_s,
+ u"Option to be passed to clang"_s},
+ {u"clang-options"_s,
+ u"A comma-separated list of options to be passed to clang"_s},
+ {u"skip-deprecated"_s,
+ u"Skip deprecated functions"_s},
+ {u"-F<path>"_s, {} },
+ {u"framework-include-paths="_s + OptionsParser::pathSyntax(),
+ u"Framework include paths used by the C++ parser"_s},
+ {u"-isystem<path>"_s, {} },
+ {u"system-include-paths="_s + OptionsParser::pathSyntax(),
+ u"System include paths used by the C++ parser"_s},
+ {u"language-level=, -std=<level>"_s,
+ languageLevelDescription()},
+ };
}
-void ApiExtractor::addTypesystemSearchPath (const QString& path)
+class ApiExtractorOptionsParser : public OptionsParser
{
- TypeDatabase::instance()->addTypesystemPath(path);
-}
+public:
+ explicit ApiExtractorOptionsParser(ApiExtractorOptions *o) : m_options(o) {}
-void ApiExtractor::addTypesystemSearchPath(const QStringList& paths)
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value,
+ OptionSource source) override;
+
+private:
+ void parseIncludePathOption(const QString &value, HeaderType headerType);
+ void parseIncludePathOption(const QStringList &values, HeaderType headerType);
+ void setLanguageLevel(const QString &value);
+
+ ApiExtractorOptions *m_options;
+};
+
+void ApiExtractorOptionsParser::parseIncludePathOption(const QString &value,
+ HeaderType headerType)
{
- for (const QString &path : paths)
- addTypesystemSearchPath(path);
+ if (value.isEmpty())
+ throw Exception(u"Empty value passed to include path option"_s);
+ const auto path = QFile::encodeName(QDir::cleanPath(value));
+ m_options->m_includePaths.append(HeaderPath{path, headerType});
}
-void ApiExtractor::setTypesystemKeywords(const QStringList &keywords)
+void ApiExtractorOptionsParser::parseIncludePathOption(const QStringList &values,
+ HeaderType headerType)
{
- TypeDatabase::instance()->setTypesystemKeywords(keywords);
+ for (const auto &value : values)
+ parseIncludePathOption(value, headerType);
}
-void ApiExtractor::addIncludePath(const HeaderPath& path)
+void ApiExtractorOptionsParser::setLanguageLevel(const QString &value)
{
- d->m_includePaths << path;
+ const QByteArray languageLevelBA = value.toLatin1();
+ const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
+ if (level == LanguageLevel::Default)
+ throw Exception(msgInvalidLanguageLevel(value));
+ m_options->m_languageLevel = level;
}
-void ApiExtractor::addIncludePath(const HeaderPaths& paths)
+bool ApiExtractorOptionsParser::handleBoolOption(const QString &key, OptionSource source)
{
- d->m_includePaths << paths;
+ static const auto isystemOption = "isystem"_L1;
+
+ switch (source) {
+ case OptionSource::CommandLine:
+ case OptionSource::ProjectFile:
+ if (key == u"use-global-header") {
+ AbstractMetaBuilder::setUseGlobalHeader(true);
+ return true;
+ }
+ if (key == u"skip-deprecated") {
+ m_options->m_skipDeprecated = true;
+ return true;
+ }
+ break;
+
+ case OptionSource::CommandLineSingleDash:
+ if (key.startsWith(u'I')) { // Shorthand path arguments -I/usr/include...
+ parseIncludePathOption(key.sliced(1), HeaderType::Standard);
+ return true;
+ }
+ if (key.startsWith(u'F')) {
+ parseIncludePathOption(key.sliced(1), HeaderType::Framework);
+ return true;
+ }
+ if (key.startsWith(isystemOption)) {
+ parseIncludePathOption(key.sliced(isystemOption.size()), HeaderType::System);
+ return true;
+ }
+ break;
+ }
+ return false;
}
-HeaderPaths ApiExtractor::includePaths() const
+bool ApiExtractorOptionsParser::handleOption(const QString &key, const QString &value,
+ OptionSource source)
{
- return d->m_includePaths;
+ if (source == OptionSource::CommandLineSingleDash) {
+ if (key == u"std") {
+ setLanguageLevel(value);
+ return true;
+ }
+ return false;
+ }
+
+ if (key == u"clang-option") {
+ m_options->m_clangOptions.append(value);
+ return true;
+ }
+ if (key == u"clang-options") {
+ m_options->m_clangOptions.append(value.split(u',', Qt::SkipEmptyParts));
+ return true;
+ }
+ if (key == u"include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts),
+ HeaderType::Standard);
+ return true;
+ }
+ if (key == u"framework-include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts),
+ HeaderType::Framework);
+ return true;
+ }
+ if (key == u"system-include-paths") {
+ parseIncludePathOption(value.split(QDir::listSeparator(), Qt::SkipEmptyParts),
+ HeaderType::System);
+ return true;
+ }
+ if (key == u"language-level") {
+ setLanguageLevel(value);
+ return true;
+ }
+
+ if (source == OptionSource::ProjectFile) {
+ if (key == u"include-path") {
+ parseIncludePathOption(value, HeaderType::Standard);
+ return true;
+ }
+ if (key == u"framework-include-path") {
+ parseIncludePathOption(value, HeaderType::Framework);
+ return true;
+ }
+ if (key == u"system-include-path") {
+ parseIncludePathOption(value, HeaderType::System);
+ return true;
+ }
+ }
+
+ return false;
}
-void ApiExtractor::setLogDirectory(const QString& logDir)
+std::shared_ptr<OptionsParser> ApiExtractor::createOptionsParser()
{
- d->m_logDirectory = logDir;
+ return std::make_shared<ApiExtractorOptionsParser>(d);
}
-void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName)
+struct ApiExtractorPrivate : public ApiExtractorOptions
{
- d->m_cppFileNames = cppFileName;
-}
+ bool runHelper(ApiExtractorFlags flags);
-QFileInfoList ApiExtractor::cppFileNames() const
+ static QString getSimplifiedContainerTypeName(const AbstractMetaType &type);
+ void addInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
+ const AbstractMetaType &type,
+ const QString &contextName);
+ void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
+ const AbstractMetaFunctionCPtr &func);
+ void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
+ const AbstractMetaClassCPtr &metaClass);
+ void collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context);
+ void collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context);
+ void collectContainerTypesFromSnippets(InstantiationCollectContext &context);
+ void collectContainerTypesFromConverterMacros(InstantiationCollectContext &context,
+ const QString &code,
+ bool toPythonMacro);
+ void addInstantiatedSmartPointer(InstantiationCollectContext &context,
+ const AbstractMetaType &type);
+
+ AbstractMetaBuilder *m_builder = nullptr;
+};
+
+ApiExtractor::ApiExtractor() :
+ d(new ApiExtractorPrivate)
{
- return d->m_cppFileNames;
}
-void ApiExtractor::setTypeSystem(const QString& typeSystemFileName)
+ApiExtractor::~ApiExtractor()
{
- d->m_typeSystemFileName = typeSystemFileName;
+ delete d->m_builder;
+ delete d;
}
-QString ApiExtractor::typeSystem() const
+HeaderPaths ApiExtractor::includePaths() const
{
- return d->m_typeSystemFileName;
+ return d->m_includePaths;
}
-void ApiExtractor::setSkipDeprecated(bool value)
+void ApiExtractor::setLogDirectory(const QString& logDir)
{
- d->m_skipDeprecated = value;
- if (d->m_builder)
- d->m_builder->setSkipDeprecated(d->m_skipDeprecated);
+ d->m_logDirectory = logDir;
}
-void ApiExtractor::setSuppressWarnings ( bool value )
+void ApiExtractor::setCppFileNames(const QFileInfoList &cppFileName)
{
- TypeDatabase::instance()->setSuppressWarnings(value);
+ d->m_cppFileNames = cppFileName;
}
-void ApiExtractor::setSilent ( bool value )
+QFileInfoList ApiExtractor::cppFileNames() const
{
- ReportHandler::setSilent(value);
+ return d->m_cppFileNames;
}
-bool ApiExtractor::setApiVersion(const QString& package, const QString &version)
+void ApiExtractor::setTypeSystem(const QString& typeSystemFileName)
{
- return TypeDatabase::setApiVersion(package, version);
+ d->m_typeSystemFileName = typeSystemFileName;
}
-void ApiExtractor::setDropTypeEntries(const QStringList &dropEntries)
+QString ApiExtractor::typeSystem() const
{
- TypeDatabase::instance()->setDropTypeEntries(dropEntries);
+ return d->m_typeSystemFileName;
}
const AbstractMetaEnumList &ApiExtractor::globalEnums() const
@@ -225,8 +340,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags)
}
const QString pattern = QDir::tempPath() + u'/'
- + m_cppFileNames.constFirst().baseName()
- + QStringLiteral("_XXXXXX.hpp");
+ + m_cppFileNames.constFirst().baseName() + "_XXXXXX.hpp"_L1;
QTemporaryFile ppFile(pattern);
bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES");
// make sure that a tempfile can be written
@@ -235,7 +349,7 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags)
<< ": " << qPrintable(ppFile.errorString()) << '\n';
return false;
}
- for (const auto &cppFileName : qAsConst(m_cppFileNames)) {
+ for (const auto &cppFileName : std::as_const(m_cppFileNames)) {
ppFile.write("#include \"");
ppFile.write(cppFileName.absoluteFilePath().toLocal8Bit());
ppFile.write("\"\n");
@@ -264,18 +378,18 @@ bool ApiExtractorPrivate::runHelper(ApiExtractorFlags flags)
arguments.append(m_clangOptions.at(i).toUtf8());
}
- for (const HeaderPath &headerPath : qAsConst(m_includePaths))
+ for (const HeaderPath &headerPath : std::as_const(m_includePaths))
arguments.append(HeaderPath::includeOption(headerPath));
+ if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions))
+ addPySideExtensions(&arguments);
arguments.append(QFile::encodeName(preprocessedCppFileName));
+
if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
qCInfo(lcShiboken).noquote().nospace()
<< "clang language level: " << int(m_languageLevel)
<< "\nclang arguments: " << arguments;
}
- if (flags.testFlag(ApiExtractorFlag::UsePySideExtensions))
- addPySideExtensions(&arguments);
-
const bool result = m_builder->build(arguments, flags, addCompilerSupportArguments,
m_languageLevel);
if (!result)
@@ -300,19 +414,17 @@ std::optional<ApiExtractorResult> ApiExtractor::run(ApiExtractorFlags flags)
InstantiationCollectContext collectContext;
d->collectInstantiatedContainersAndSmartPointers(collectContext);
- auto *data = new ApiExtractorResultData;
-
- classListToCList(d->m_builder->takeClasses(), &data->m_metaClasses);
- classListToCList(d->m_builder->takeTemplates(), &data->m_templates);
- classListToCList(d->m_builder->takeSmartPointers(), &data->m_smartPointers);
- data->m_globalFunctions = d->m_builder->globalFunctions();
- data->m_globalEnums = d->m_builder->globalEnums();
- data->m_enums = d->m_builder->typeEntryToEnumsHash();
- data->m_flags = flags;
- qSwap(data->m_instantiatedContainers, collectContext.instantiatedContainers);
- qSwap(data->m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers);
- qSwap(data->m_synthesizedTypeEntries, collectContext.m_synthesizedTypeEntries);
- return ApiExtractorResult(data);
+ ApiExtractorResult result;
+ classListToCList(d->m_builder->takeClasses(), &result.m_metaClasses);
+ classListToCList(d->m_builder->takeSmartPointers(), &result.m_smartPointers);
+ result.m_globalFunctions = d->m_builder->globalFunctions();
+ result.m_globalEnums = d->m_builder->globalEnums();
+ result.m_enums = d->m_builder->typeEntryToEnumsHash();
+ result.m_flags = flags;
+ result.m_typedefTargetToName = d->m_builder->typedefTargetToName();
+ qSwap(result.m_instantiatedContainers, collectContext.instantiatedContainers);
+ qSwap(result.m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers);
+ return result;
}
LanguageLevel ApiExtractor::languageLevel() const
@@ -320,26 +432,11 @@ LanguageLevel ApiExtractor::languageLevel() const
return d->m_languageLevel;
}
-void ApiExtractor::setLanguageLevel(LanguageLevel languageLevel)
-{
- d->m_languageLevel = languageLevel;
-}
-
QStringList ApiExtractor::clangOptions() const
{
return d->m_clangOptions;
}
-void ApiExtractor::setClangOptions(const QStringList &co)
-{
- d->m_clangOptions = co;
-}
-
-void ApiExtractor::setUseGlobalHeader(bool h)
-{
- AbstractMetaBuilder::setUseGlobalHeader(h);
-}
-
AbstractMetaFunctionPtr
ApiExtractor::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes)
@@ -350,15 +447,15 @@ AbstractMetaFunctionPtr
AbstractMetaFunctionPtr
ApiExtractor::inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass)
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass)
{
return AbstractMetaBuilder::inheritTemplateMember(function, templateTypes,
templateClass, subclass);
}
-AbstractMetaClass *ApiExtractor::inheritTemplateClass(ComplexTypeEntry *te,
- const AbstractMetaClass *templateClass,
+AbstractMetaClassPtr ApiExtractor::inheritTemplateClass(const ComplexTypeEntryPtr &te,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags)
{
@@ -409,7 +506,7 @@ AbstractMetaType canonicalSmartPtrInstantiation(const AbstractMetaType &type)
return fixedType;
}
-static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType &smartPtrType)
+static inline TypeEntryCPtr pointeeTypeEntry(const AbstractMetaType &smartPtrType)
{
return smartPtrType.instantiations().constFirst().typeEntry();
}
@@ -437,12 +534,12 @@ ApiExtractorPrivate::addInstantiatedContainersAndSmartPointers(InstantiationColl
return;
}
if (type.hasTemplateChildren()) {
- QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer");
+ const auto piece = isContainer ? "container"_L1 : "smart pointer"_L1;
QString warning =
QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template"
" arguments.").arg(piece, type.originalTypeDescription());
if (!contextName.isEmpty())
- warning.append(QStringLiteral(" Calling context: ") + contextName);
+ warning.append(" Calling context: "_L1 + contextName);
qCWarning(lcShiboken).noquote().nospace() << warning;
return;
@@ -485,12 +582,12 @@ static FunctionModification invalidateArgMod(const AbstractMetaFunctionCPtr &f,
}
static void addOwnerModification(const AbstractMetaFunctionCList &functions,
- ComplexTypeEntry *typeEntry)
+ const ComplexTypeEntryPtr &typeEntry)
{
for (const auto &f : functions) {
if (!f->arguments().isEmpty()
&& f->arguments().constFirst().type().indirections() > 0) {
- qSharedPointerConstCast<AbstractMetaFunction>(f)->clearModificationsCache();
+ std::const_pointer_cast<AbstractMetaFunction>(f)->clearModificationsCache();
typeEntry->addFunctionModification(invalidateArgMod(f));
}
}
@@ -500,22 +597,45 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex
const AbstractMetaType &type)
{
InstantiatedSmartPointer smp;
- smp.type = simplifiedType(type);
+ smp.type = canonicalSmartPtrInstantiation(type);
smp.smartPointer = AbstractMetaClass::findClass(m_builder->smartPointers(),
type.typeEntry());
Q_ASSERT(smp.smartPointer);
const auto &instantiatedType = type.instantiations().constFirst();
- auto *ste = static_cast<const SmartPointerTypeEntry *>(smp.smartPointer->typeEntry());
- auto *typedefEntry = new TypedefEntry(SmartPointerTypeEntry::getTargetName(smp.type),
- ste->name(), ste->version(), ste->parent());
+ const auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(smp.smartPointer->typeEntry());
+ QString name = ste->getTargetName(smp.type);
+ auto parentTypeEntry = ste->parent();
+ InheritTemplateFlags flags;
+
+ auto colonPos = name.lastIndexOf(u"::");
+ const bool withinNameSpace = colonPos != -1;
+ if (withinNameSpace) { // user defined
+ const QString nameSpace = name.left(colonPos);
+ name.remove(0, colonPos + 2);
+ const auto nameSpaces = TypeDatabase::instance()->findNamespaceTypes(nameSpace);
+ if (nameSpaces.isEmpty())
+ throw Exception(msgNamespaceNotFound(name));
+ parentTypeEntry = nameSpaces.constFirst();
+ } else {
+ flags.setFlag(InheritTemplateFlag::SetEnclosingClass);
+ }
+
+ TypedefEntryPtr typedefEntry(new TypedefEntry(name, ste->name(), ste->version(),
+ parentTypeEntry));
typedefEntry->setTargetLangPackage(ste->targetLangPackage());
- auto *instantiationEntry = TypeDatabase::initializeTypeDefEntry(typedefEntry, ste);
+ auto instantiationEntry = TypeDatabase::initializeTypeDefEntry(typedefEntry, ste);
smp.specialized = ApiExtractor::inheritTemplateClass(instantiationEntry, smp.smartPointer,
- {instantiatedType},
- InheritTemplateFlag::SetEnclosingClass);
+ {instantiatedType}, flags);
Q_ASSERT(smp.specialized);
+ if (withinNameSpace) { // move class to desired namespace
+ const auto enclClass = AbstractMetaClass::findClass(m_builder->classes(), parentTypeEntry);
+ Q_ASSERT(enclClass);
+ auto specialized = std::const_pointer_cast<AbstractMetaClass>(smp.specialized);
+ specialized->setEnclosingClass(enclClass);
+ enclClass->addInnerClass(specialized);
+ }
if (instantiationEntry->isComplex()) {
addOwnerModification(smp.specialized->queryFunctions(FunctionQueryOption::Constructors),
@@ -527,8 +647,6 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex
}
context.instantiatedSmartPointers.append(smp);
- context.m_synthesizedTypeEntries.append(typedefEntry);
- context.m_synthesizedTypeEntries.append(instantiationEntry);
}
void
@@ -536,22 +654,34 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation
const AbstractMetaFunctionCPtr &func)
{
addInstantiatedContainersAndSmartPointers(context, func->type(), func->signature());
- for (const AbstractMetaArgument &arg : func->arguments())
- addInstantiatedContainersAndSmartPointers(context, arg.type(), func->signature());
+ for (const AbstractMetaArgument &arg : func->arguments()) {
+ const auto argType = arg.type();
+ const auto type = argType.viewOn() != nullptr ? *argType.viewOn() : argType;
+ addInstantiatedContainersAndSmartPointers(context, type, func->signature());
+ }
}
void
ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(InstantiationCollectContext &context,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
if (!metaClass->typeEntry()->generateCode())
return;
for (const auto &func : metaClass->functions())
collectInstantiatedContainersAndSmartPointers(context, func);
+ for (const auto &func : metaClass->userAddedPythonOverrides())
+ collectInstantiatedContainersAndSmartPointers(context, func);
for (const AbstractMetaField &field : metaClass->fields())
addInstantiatedContainersAndSmartPointers(context, field.type(), field.name());
- for (auto *innerClass : metaClass->innerClasses())
- collectInstantiatedContainersAndSmartPointers(context, innerClass);
+
+ // The list of inner classes might be extended when smart pointer
+ // instantiations are specified to be in namespaces.
+ const auto &innerClasses = metaClass->innerClasses();
+ for (auto i = innerClasses.size() - 1; i >= 0; --i) {
+ const auto innerClass = innerClasses.at(i);
+ if (!innerClass->typeEntry()->isSmartPointer())
+ collectInstantiatedContainersAndSmartPointers(context, innerClass);
+ }
}
void
@@ -560,7 +690,7 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation
collectInstantiatedOpqaqueContainers(context);
for (const auto &func : m_builder->globalFunctions())
collectInstantiatedContainersAndSmartPointers(context, func);
- for (auto metaClass : m_builder->classes())
+ for (const auto &metaClass : m_builder->classes())
collectInstantiatedContainersAndSmartPointers(context, metaClass);
collectContainerTypesFromSnippets(context);
}
@@ -569,12 +699,12 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation
// the current package or, for primitive types, if the container is in the
// current package.
static bool generateOpaqueContainer(const AbstractMetaType &type,
- const TypeSystemTypeEntry *moduleEntry)
+ const TypeSystemTypeEntryCPtr &moduleEntry)
{
- auto *te = type.instantiations().constFirst().typeEntry();
- auto *typeModuleEntry = te->typeSystemTypeEntry();
+ auto te = type.instantiations().constFirst().typeEntry();
+ auto typeModuleEntry = typeSystemTypeEntry(te);
return typeModuleEntry == moduleEntry
- || (te->isPrimitive() && type.typeEntry()->typeSystemTypeEntry() == moduleEntry);
+ || (te->isPrimitive() && typeSystemTypeEntry(type.typeEntry()) == moduleEntry);
}
void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationCollectContext &context)
@@ -582,13 +712,12 @@ void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationColl
// Add all instantiations of opaque containers for types from the current
// module.
auto *td = TypeDatabase::instance();
- const auto *moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
+ const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
const auto &containers = td->containerTypes();
- for (const auto *container : containers) {
+ for (const auto &container : containers) {
for (const auto &oc : container->opaqueContainers()) {
QString errorMessage;
- const QString typeName = container->qualifiedCppName() + u'<'
- + oc.instantiation + u'>';
+ const QString typeName = container->qualifiedCppName() + oc.templateParameters();
auto typeOpt = AbstractMetaType::fromString(typeName, &errorMessage);
if (typeOpt.has_value()
&& generateOpaqueContainer(typeOpt.value(), moduleEntry)) {
@@ -601,15 +730,18 @@ void ApiExtractorPrivate::collectInstantiatedOpqaqueContainers(InstantiationColl
static void getCode(QStringList &code, const CodeSnipList &codeSnips)
{
- for (const CodeSnip &snip : qAsConst(codeSnips))
+ for (const CodeSnip &snip : std::as_const(codeSnips))
code.append(snip.code());
}
-static void getCode(QStringList &code, const TypeEntry *type)
+static void getCode(QStringList &code, const TypeEntryCPtr &type)
{
- getCode(code, type->codeSnips());
+ if (type->isComplex())
+ getCode(code, std::static_pointer_cast<const ComplexTypeEntry>(type)->codeSnips());
+ else if (type->isTypeSystem())
+ getCode(code, std::static_pointer_cast<const TypeSystemTypeEntry>(type)->codeSnips());
- CustomConversion *customConversion = type->customConversion();
+ auto customConversion = CustomConversion::getCustomConversion(type);
if (!customConversion)
return;
@@ -620,31 +752,31 @@ static void getCode(QStringList &code, const TypeEntry *type)
if (toCppConversions.isEmpty())
return;
- for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions))
- code.append(toNative->conversion());
+ for (const auto &toNative : std::as_const(toCppConversions))
+ code.append(toNative.conversion());
}
void ApiExtractorPrivate::collectContainerTypesFromSnippets(InstantiationCollectContext &context)
{
QStringList snips;
auto *td = TypeDatabase::instance();
- const PrimitiveTypeEntryList &primitiveTypeList = td->primitiveTypes();
- for (const PrimitiveTypeEntry *type : primitiveTypeList)
+ const PrimitiveTypeEntryCList &primitiveTypeList = td->primitiveTypes();
+ for (const auto &type : primitiveTypeList)
getCode(snips, type);
- const ContainerTypeEntryList &containerTypeList = td->containerTypes();
- for (const ContainerTypeEntry *type : containerTypeList)
+ const ContainerTypeEntryCList &containerTypeList = td->containerTypes();
+ for (const auto &type : containerTypeList)
getCode(snips, type);
- for (auto metaClass : m_builder->classes())
+ for (const auto &metaClass : m_builder->classes())
getCode(snips, metaClass->typeEntry());
- const TypeSystemTypeEntry *moduleEntry = td->defaultTypeSystemType();
+ const auto moduleEntry = td->defaultTypeSystemType();
Q_ASSERT(moduleEntry);
getCode(snips, moduleEntry);
for (const auto &func : m_builder->globalFunctions())
getCode(snips, func->injectedCodeSnips());
- for (const QString &code : qAsConst(snips)) {
+ for (const QString &code : std::as_const(snips)) {
collectContainerTypesFromConverterMacros(context, code, true);
collectContainerTypesFromConverterMacros(context, code, false);
}
@@ -656,8 +788,8 @@ ApiExtractorPrivate::collectContainerTypesFromConverterMacros(InstantiationColle
bool toPythonMacro)
{
QString convMacro = toPythonMacro ? u"%CONVERTTOPYTHON["_s : u"%CONVERTTOCPP["_s;
- int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP");
- int start = 0;
+ const qsizetype offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP");
+ qsizetype start = 0;
QString errorMessage;
while ((start = code.indexOf(convMacro, start)) != -1) {
int end = code.indexOf(u']', start);
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.h b/sources/shiboken6/ApiExtractor/apiextractor.h
index fd84f6870..feae9454c 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.h
+++ b/sources/shiboken6/ApiExtractor/apiextractor.h
@@ -5,10 +5,10 @@
#define APIEXTRACTOR_H
#include "abstractmetalang_typedefs.h"
-#include "abstractmetatype.h"
#include "apiextractorflags.h"
#include "header_paths.h"
#include "clangparser/compilersupport.h"
+#include "typesystem_typedefs.h"
#include <QtCore/QFileInfoList>
#include <QtCore/QStringList>
@@ -20,6 +20,8 @@ class AbstractMetaClass;
class AbstractMetaEnum;
class AbstractMetaFunction;
class ComplexTypeEntry;
+struct OptionDescription;
+class OptionsParser;
QT_BEGIN_NAMESPACE
class QDebug;
@@ -36,27 +38,17 @@ public:
ApiExtractor();
~ApiExtractor();
+ static QList<OptionDescription> options();
+ std::shared_ptr<OptionsParser> createOptionsParser();
+
void setTypeSystem(const QString& typeSystemFileName);
QString typeSystem() const;
void setCppFileNames(const QFileInfoList &cppFileNames);
QFileInfoList cppFileNames() const;
- void setSkipDeprecated(bool value);
- static void setSuppressWarnings(bool value);
- static void setSilent(bool value);
- static void addTypesystemSearchPath(const QString &path);
- static void addTypesystemSearchPath(const QStringList& paths);
- static void setTypesystemKeywords(const QStringList& keywords);
- void addIncludePath(const HeaderPath& path);
- void addIncludePath(const HeaderPaths& paths);
HeaderPaths includePaths() const;
void setLogDirectory(const QString& logDir);
- static bool setApiVersion(const QString &package, const QString &version);
- static void setDropTypeEntries(const QStringList &dropEntries);
LanguageLevel languageLevel() const;
- void setLanguageLevel(LanguageLevel languageLevel);
QStringList clangOptions() const;
- void setClangOptions(const QStringList &co);
- static void setUseGlobalHeader(bool h);
const AbstractMetaEnumList &globalEnums() const;
const AbstractMetaFunctionCList &globalFunctions() const;
@@ -74,13 +66,13 @@ public:
static AbstractMetaFunctionPtr
inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
const AbstractMetaTypeList &templateTypes,
- const AbstractMetaClass *templateClass,
- AbstractMetaClass *subclass);
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass);
/// Forwards to AbstractMetaBuilder::inheritTemplateClass()
- static AbstractMetaClass *
- inheritTemplateClass(ComplexTypeEntry *te,
- const AbstractMetaClass *templateClass,
+ static AbstractMetaClassPtr
+ inheritTemplateClass(const ComplexTypeEntryPtr &te,
+ const AbstractMetaClassCPtr &templateClass,
const AbstractMetaTypeList &templateTypes,
InheritTemplateFlags flags = {});
diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp
index 8067290d1..2a48a30d1 100644
--- a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp
+++ b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp
@@ -2,98 +2,84 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "apiextractorresult.h"
-#include "apiextractorresultdata_p.h"
#include "abstractmetalang.h"
#include "abstractmetaenum.h"
#include "enumtypeentry.h"
#include "flagstypeentry.h"
-ApiExtractorResultData::ApiExtractorResultData() = default;
-
-ApiExtractorResultData::~ApiExtractorResultData()
-{
- qDeleteAll(m_smartPointers);
- qDeleteAll(m_metaClasses);
- qDeleteAll(m_templates);
- for (auto &smp : m_instantiatedSmartPointers)
- delete smp.specialized;
- qDeleteAll(m_synthesizedTypeEntries);
-}
-
-ApiExtractorResult::ApiExtractorResult() : d(new ApiExtractorResultData)
-{
-}
-
-ApiExtractorResult::ApiExtractorResult(ApiExtractorResultData *data) :
- d(data)
-{
-}
+ApiExtractorResult::ApiExtractorResult() = default;
ApiExtractorResult::ApiExtractorResult(const ApiExtractorResult &) = default;
ApiExtractorResult &ApiExtractorResult::operator=(const ApiExtractorResult &) = default;
-ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) = default;
+ApiExtractorResult::ApiExtractorResult(ApiExtractorResult &&) noexcept = default;
-ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) = default;
+ApiExtractorResult &ApiExtractorResult::operator=(ApiExtractorResult &&) noexcept = default;
ApiExtractorResult::~ApiExtractorResult() = default;
const AbstractMetaEnumList &ApiExtractorResult::globalEnums() const
{
- return d->m_globalEnums;
+ return m_globalEnums;
}
const AbstractMetaFunctionCList &ApiExtractorResult::globalFunctions() const
{
- return d->m_globalFunctions;
+ return m_globalFunctions;
}
const AbstractMetaClassCList &ApiExtractorResult::classes() const
{
- return d->m_metaClasses;
+ return m_metaClasses;
}
const AbstractMetaClassCList &ApiExtractorResult::smartPointers() const
{
- return d->m_smartPointers;
+ return m_smartPointers;
}
const AbstractMetaTypeList &ApiExtractorResult::instantiatedContainers() const
{
- return d->m_instantiatedContainers;
+ return m_instantiatedContainers;
}
const InstantiatedSmartPointers &ApiExtractorResult::instantiatedSmartPointers() const
{
- return d->m_instantiatedSmartPointers;
+ return m_instantiatedSmartPointers;
+}
+
+const QMultiHash<QString, QString> &ApiExtractorResult::typedefTargetToName() const
+{
+ return m_typedefTargetToName;
}
ApiExtractorFlags ApiExtractorResult::flags() const
{
- return d->m_flags;
+ return m_flags;
}
void ApiExtractorResult::setFlags(ApiExtractorFlags f)
{
- d->m_flags = f;
+ m_flags = f;
}
-std::optional<AbstractMetaEnum> ApiExtractorResult::findAbstractMetaEnum(const TypeEntry *typeEntry) const
+std::optional<AbstractMetaEnum>
+ ApiExtractorResult::findAbstractMetaEnum(TypeEntryCPtr typeEntry) const
{
if (typeEntry && typeEntry->isFlags())
- typeEntry = static_cast<const FlagsTypeEntry *>(typeEntry)->originator();
- const auto it = d->m_enums.constFind(typeEntry);
- if (it == d->m_enums.constEnd())
+ typeEntry = std::static_pointer_cast<const FlagsTypeEntry>(typeEntry)->originator();
+ const auto it = m_enums.constFind(typeEntry);
+ if (it == m_enums.constEnd())
return {};
return it.value();
}
-AbstractMetaFunctionCList ApiExtractorResult::implicitConversions(const TypeEntry *type) const
+AbstractMetaFunctionCList ApiExtractorResult::implicitConversions(const TypeEntryCPtr &type) const
{
if (type->isValue()) {
- if (auto metaClass = AbstractMetaClass::findClass(d->m_metaClasses, type))
+ if (auto metaClass = AbstractMetaClass::findClass(m_metaClasses, type))
return metaClass->implicitConversions();
}
return {};
diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.h b/sources/shiboken6/ApiExtractor/apiextractorresult.h
index 8dd3383bf..88a2093f1 100644
--- a/sources/shiboken6/ApiExtractor/apiextractorresult.h
+++ b/sources/shiboken6/ApiExtractor/apiextractorresult.h
@@ -4,14 +4,13 @@
#ifndef APIEXTRACTORRESULT_H
#define APIEXTRACTORRESULT_H
-#include "abstractmetalang.h"
#include "apiextractorflags.h"
-#include "abstractmetaenum.h"
#include "abstractmetatype.h"
+#include "abstractmetalang_typedefs.h"
#include "typesystem_typedefs.h"
#include <QtCore/QHash>
-#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QMultiHash>
#include <optional>
@@ -19,8 +18,8 @@ class ApiExtractorResultData;
struct InstantiatedSmartPointer
{
- const AbstractMetaClass *smartPointer = nullptr; // Template class
- const AbstractMetaClass *specialized = nullptr; // Specialized for type
+ AbstractMetaClassCPtr smartPointer; // Template class
+ AbstractMetaClassCPtr specialized; // Specialized for type
AbstractMetaType type;
};
@@ -31,11 +30,10 @@ class ApiExtractorResult
{
public:
ApiExtractorResult();
- explicit ApiExtractorResult(ApiExtractorResultData *data);
ApiExtractorResult(const ApiExtractorResult &);
ApiExtractorResult &operator=(const ApiExtractorResult &);
- ApiExtractorResult(ApiExtractorResult &&);
- ApiExtractorResult &operator=(ApiExtractorResult &&);
+ ApiExtractorResult(ApiExtractorResult &&) noexcept;
+ ApiExtractorResult &operator=(ApiExtractorResult &&) noexcept;
~ApiExtractorResult();
const AbstractMetaEnumList &globalEnums() const;
@@ -46,22 +44,35 @@ public:
const AbstractMetaTypeList &instantiatedContainers() const;
const InstantiatedSmartPointers &instantiatedSmartPointers() const;
+ const QMultiHash<QString, QString> &typedefTargetToName() const;
+
// Query functions for the generators
- std::optional<AbstractMetaEnum> findAbstractMetaEnum(const TypeEntry* typeEntry) const;
+ std::optional<AbstractMetaEnum>
+ findAbstractMetaEnum(TypeEntryCPtr typeEntry) const;
/// Retrieves a list of constructors used in implicit conversions
/// available on the given type. The TypeEntry must be a value-type
/// or else it will return an empty list.
/// \param type a TypeEntry that is expected to be a value-type
/// \return a list of constructors that could be used as implicit converters
- AbstractMetaFunctionCList implicitConversions(const TypeEntry *type) const;
+ AbstractMetaFunctionCList implicitConversions(const TypeEntryCPtr &type) const;
AbstractMetaFunctionCList implicitConversions(const AbstractMetaType &metaType) const;
ApiExtractorFlags flags() const;
void setFlags(ApiExtractorFlags f);
private:
- QExplicitlySharedDataPointer<ApiExtractorResultData> d;
+ AbstractMetaClassCList m_metaClasses;
+ AbstractMetaClassCList m_smartPointers;
+ AbstractMetaFunctionCList m_globalFunctions;
+ AbstractMetaEnumList m_globalEnums;
+ AbstractMetaTypeList m_instantiatedContainers;
+ InstantiatedSmartPointers m_instantiatedSmartPointers;
+ QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums;
+ QMultiHash<QString, QString> m_typedefTargetToName;
+ ApiExtractorFlags m_flags;
+
+ friend class ApiExtractor;
};
#endif // APIEXTRACTORRESULT_H
diff --git a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h b/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h
deleted file mode 100644
index 2750b0c37..000000000
--- a/sources/shiboken6/ApiExtractor/apiextractorresultdata_p.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef APIEXTRACTORRESULTDATA_P_H
-#define APIEXTRACTORRESULTDATA_P_H
-
-#include "apiextractorresult.h"
-
-#include <QtCore/QHash>
-#include <QtCore/QSharedData>
-
-class ApiExtractorResultData : public QSharedData
-{
-public:
- ApiExtractorResultData();
- ~ApiExtractorResultData();
-
- AbstractMetaClassCList m_metaClasses;
- AbstractMetaClassCList m_templates; // not exposed, just for ownership
- AbstractMetaClassCList m_smartPointers;
- AbstractMetaFunctionCList m_globalFunctions;
- AbstractMetaEnumList m_globalEnums;
- AbstractMetaTypeList m_instantiatedContainers;
- InstantiatedSmartPointers m_instantiatedSmartPointers;
- QHash<const TypeEntry *, AbstractMetaEnum> m_enums;
- QList<const TypeEntry *> m_synthesizedTypeEntries; // not exposed, just for ownership
- ApiExtractorFlags m_flags;
-};
-
-#endif // APIEXTRACTORRESULTDATA_P_H
diff --git a/sources/shiboken6/ApiExtractor/arraytypeentry.h b/sources/shiboken6/ApiExtractor/arraytypeentry.h
index d520fa0b3..5b9bb191e 100644
--- a/sources/shiboken6/ApiExtractor/arraytypeentry.h
+++ b/sources/shiboken6/ApiExtractor/arraytypeentry.h
@@ -11,11 +11,11 @@ class ArrayTypeEntryPrivate;
class ArrayTypeEntry : public TypeEntry
{
public:
- explicit ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr,
- const TypeEntry *parent);
+ explicit ArrayTypeEntry(const TypeEntryCPtr &nested_type, const QVersionNumber &vr,
+ const TypeEntryCPtr &parent);
- void setNestedTypeEntry(TypeEntry *nested);
- const TypeEntry *nestedTypeEntry() const;
+ void setNestedTypeEntry(const TypeEntryPtr &nested);
+ TypeEntryCPtr nestedTypeEntry() const;
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
index bc27240df..31e7efb05 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
@@ -4,6 +4,7 @@
#include "clangbuilder.h"
#include "compilersupport.h"
#include "clangutils.h"
+#include "clangdebugutils.h"
#include <codemodel.h>
#include <reporthandler.h>
@@ -25,9 +26,6 @@ using namespace Qt::StringLiterals;
namespace clang {
-static inline QString colonColon() { return QStringLiteral("::"); }
-static inline QString templateBrackets() { return QStringLiteral("<>"); }
-
static inline bool isClassCursor(const CXCursor &c)
{
return c.kind == CXCursor_ClassDecl || c.kind == CXCursor_StructDecl
@@ -48,7 +46,7 @@ static inline bool withinClassDeclaration(const CXCursor &cursor)
static QString fixTypeName(QString t)
{
// Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**"
- int pos = t.size() - 1;
+ auto pos = t.size() - 1;
for (; pos >= 0 && (t.at(pos) == u'&' || t.at(pos) == u'*'); --pos) {}
if (pos > 0 && t.at(pos) == u' ')
t.remove(pos, 1);
@@ -63,7 +61,7 @@ static bool insertTemplateParameterIntoClassName(const QString &parmName, QStrin
if (Q_UNLIKELY(!name->endsWith(u'>')))
return false;
const bool needsComma = name->at(name->size() - 2) != u'<';
- const int insertionPos = name->size() - 1;
+ const auto insertionPos = name->size() - 1;
name->insert(insertionPos, parmName);
if (needsComma)
name->insert(insertionPos, u',');
@@ -115,8 +113,17 @@ static bool isSigned(CXTypeKind kind)
class BuilderPrivate {
public:
+ Q_DISABLE_COPY_MOVE(BuilderPrivate)
+
+ enum class SpecialSystemHeader {
+ None,
+ Types,
+ OpenGL,
+ WhiteListed,
+ WhiteListedPath
+ };
+
using CursorClassHash = QHash<CXCursor, ClassModelItem>;
- using CursorTypedefHash = QHash<CXCursor, TypeDefModelItem>;
using TypeInfoHash = QHash<CXType, TypeInfo>;
explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel)
@@ -182,10 +189,9 @@ public:
std::pair<QString, ClassModelItem> getBaseClass(CXType type) const;
void addBaseClass(const CXCursor &cursor);
- template <class Item>
- void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const;
-
+ SpecialSystemHeader specialSystemHeader(const QString &fileName) const;
bool visitHeader(const QString &fileName) const;
+ static const char *specialSystemHeaderReason(SpecialSystemHeader sh);
void setFileName(const CXCursor &cursor, _CodeModelItem *item);
@@ -198,7 +204,6 @@ public:
// classes can be correctly parented in case of forward-declared inner classes
// (QMetaObject::Connection)
CursorClassHash m_cursorClassHash;
- CursorTypedefHash m_cursorTypedefHash;
mutable TypeInfoHash m_typeInfoHash; // Cache type information
mutable QHash<QString, TemplateTypeAliasModelItem> m_templateTypeAliases;
@@ -209,21 +214,22 @@ public:
ArgumentModelItem m_currentArgument;
VariableModelItem m_currentField;
TemplateTypeAliasModelItem m_currentTemplateTypeAlias;
- QStringList m_systemIncludes; // files, like "memory"
- QStringList m_systemIncludePaths; // paths, like "/usr/include/Qt/"
+ QStringList m_forceProcessSystemIncludes; // files, like "memory"
+ QStringList m_forceProcessSystemIncludePaths; // paths, like "/usr/include/Qt/"
QString m_usingTypeRef; // Base classes in "using Base::member;"
bool m_withinUsingDeclaration = false;
int m_anonymousEnumCount = 0;
CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal;
bool m_withinFriendDecl = false;
+ mutable QHash<QString, SpecialSystemHeader> m_systemHeaders;
};
bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t)
{
QString className = getCursorSpelling(cursor);
m_currentClass.reset(new _ClassModelItem(m_model, className));
- setFileName(cursor, m_currentClass.data());
+ setFileName(cursor, m_currentClass.get());
m_currentClass->setClassType(t);
// Some inner class? Note that it does not need to be (lexically) contained in a
// class since it is possible to forward declare an inner class:
@@ -266,7 +272,7 @@ static QString msgCannotDetermineException(const std::string_view &snippetV)
const qsizetype length = qsizetype(truncate ? newLine : snippetV.size());
QString snippet = QString::fromUtf8(snippetV.data(), length);
if (truncate)
- snippet += QStringLiteral("...");
+ snippet += "..."_L1;
return u"Cannot determine exception specification: \""_s + snippet + u'"';
}
@@ -327,9 +333,11 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor,
// Apply type fixes to "operator X &" -> "operator X&"
if (name.startsWith(u"operator "))
name = fixTypeName(name);
- FunctionModelItem result(new _FunctionModelItem(m_model, name));
- setFileName(cursor, result.data());
- result->setType(createTypeInfo(clang_getCursorResultType(cursor)));
+ auto result = std::make_shared<_FunctionModelItem>(m_model, name);
+ setFileName(cursor, result.get());
+ const auto type = clang_getCursorResultType(cursor);
+ result->setType(createTypeInfo(type));
+ result->setScopeResolution(hasScopeResolution(type));
result->setFunctionType(t);
result->setScope(m_scope);
result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static);
@@ -338,7 +346,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor,
case CXAvailability_Available:
break;
case CXAvailability_Deprecated:
- result->setDeprecated(true);
+ result->setAttribute(FunctionAttribute::Deprecated);
break;
case CXAvailability_NotAvailable: // "Foo(const Foo&) = delete;"
result->setDeleted(true);
@@ -381,9 +389,9 @@ FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor,
auto result = createFunction(cursor, functionType, isTemplateCode);
result->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
result->setConstant(clang_CXXMethod_isConst(cursor) != 0);
- result->setStatic(clang_CXXMethod_isStatic(cursor) != 0);
- result->setVirtual(clang_CXXMethod_isVirtual(cursor) != 0);
- result->setAbstract(clang_CXXMethod_isPureVirtual(cursor) != 0);
+ result->setAttribute(FunctionAttribute::Static, clang_CXXMethod_isStatic(cursor) != 0);
+ result->setAttribute(FunctionAttribute::Virtual, clang_CXXMethod_isVirtual(cursor) != 0);
+ result->setAttribute(FunctionAttribute::Abstract, clang_CXXMethod_isPureVirtual(cursor) != 0);
return result;
}
@@ -399,13 +407,14 @@ void BuilderPrivate::qualifyConstructor(const CXCursor &cursor)
&& m_currentFunction->arguments().size() == 1
&& clang_CXXConstructor_isCopyConstructor(cursor) == 0
&& clang_CXXConstructor_isMoveConstructor(cursor) == 0) {
- m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0);
+ m_currentFunction->setAttribute(FunctionAttribute::Explicit,
+ clang_CXXConstructor_isConvertingConstructor(cursor) == 0);
}
}
TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const
{
- return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor)));
+ return std::make_shared<_TemplateParameterModelItem>(m_model, getCursorSpelling(cursor));
}
TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const
@@ -418,11 +427,12 @@ TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const
// CXCursor_VarDecl, CXCursor_FieldDecl cursors
void BuilderPrivate::addField(const CXCursor &cursor)
{
- VariableModelItem field(new _VariableModelItem(m_model, getCursorSpelling(cursor)));
+ auto field = std::make_shared<_VariableModelItem>(m_model, getCursorSpelling(cursor));
field->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
field->setScope(m_scope);
field->setType(createTypeInfo(cursor));
field->setMutable(clang_CXXField_isMutable(cursor) != 0);
+ setFileName(cursor, field.get());
m_currentField = field;
m_scopeStack.back()->addVariable(field);
}
@@ -438,7 +448,7 @@ static QStringList qualifiedName(const QString &t)
end = t.size();
int lastPos = 0;
while (true) {
- const int nextPos = t.indexOf(colonColon(), lastPos);
+ const int nextPos = t.indexOf(u"::"_s, lastPos);
if (nextPos < 0 || nextPos >= end)
break;
result.append(t.mid(lastPos, nextPos - lastPos));
@@ -502,7 +512,7 @@ void BuilderPrivate::addTemplateInstantiations(const CXType &type,
&& !t->instantiations().isEmpty();
if (!parsed)
t->setInstantiations({});
- const QPair<int, int> pos = parsed
+ const auto pos = parsed
? parseTemplateArgumentList(*typeName, dummyTemplateArgumentHandler)
: t->parseTemplateArgumentList(*typeName);
if (pos.first != -1 && pos.second != -1 && pos.second > pos.first)
@@ -556,7 +566,7 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type,
typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0);
typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0);
- QString typeName = getTypeName(nestedType);
+ QString typeName = getResolvedTypeName(nestedType);
while (TypeInfo::stripLeadingConst(&typeName)
|| TypeInfo::stripLeadingVolatile(&typeName)) {
}
@@ -566,14 +576,14 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type,
// the typedef source is named "type-parameter-0-0". Convert it back to the
// template parameter name. The CXTypes are the same for all templates and
// must not be cached.
- if (!m_currentClass.isNull() && typeName.startsWith(u"type-parameter-0-")) {
+ if (m_currentClass && typeName.startsWith(u"type-parameter-0-")) {
if (cacheable != nullptr)
*cacheable = false;
bool ok;
const int n = QStringView{typeName}.mid(17).toInt(&ok);
if (ok) {
auto currentTemplate = currentTemplateClass();
- if (!currentTemplate.isNull() && n < currentTemplate->templateParameters().size())
+ if (currentTemplate && n < currentTemplate->templateParameters().size())
typeName = currentTemplate->templateParameters().at(n)->name();
}
}
@@ -604,19 +614,18 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType)
{
const QString target = getCursorSpelling(cursor);
- TypeDefModelItem item(new _TypeDefModelItem(m_model, target));
- setFileName(cursor, item.data());
+ auto item = std::make_shared<_TypeDefModelItem>(m_model, target);
+ setFileName(cursor, item.get());
item->setType(createTypeInfo(cxType));
item->setScope(m_scope);
m_scopeStack.back()->addTypeDef(item);
- m_cursorTypedefHash.insert(cursor, item);
}
ClassModelItem BuilderPrivate::currentTemplateClass() const
{
- for (int i = m_scopeStack.size() - 1; i >= 0; --i) {
- auto klass = qSharedPointerDynamicCast<_ClassModelItem>(m_scopeStack.at(i));
- if (!klass.isNull() && klass->isTemplate())
+ for (auto i = m_scopeStack.size() - 1; i >= 0; --i) {
+ auto klass = std::dynamic_pointer_cast<_ClassModelItem>(m_scopeStack.at(i));
+ if (klass && klass->isTemplate())
return klass;
}
return {};
@@ -626,7 +635,7 @@ void BuilderPrivate::startTemplateTypeAlias(const CXCursor &cursor)
{
const QString target = getCursorSpelling(cursor);
m_currentTemplateTypeAlias.reset(new _TemplateTypeAliasModelItem(m_model, target));
- setFileName(cursor, m_currentTemplateTypeAlias.data());
+ setFileName(cursor, m_currentTemplateTypeAlias.get());
m_currentTemplateTypeAlias->setScope(m_scope);
}
@@ -651,11 +660,17 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c
if (equalSign == std::string::npos)
return QString();
++equalSign;
- return QString::fromLocal8Bit(snippet.data() + equalSign,
- qsizetype(snippet.size() - equalSign)).trimmed();
+ QString result = QString::fromLocal8Bit(snippet.data() + equalSign,
+ qsizetype(snippet.size() - equalSign));
+ // Fix a default expression as read from code. Simplify white space
+ result.remove(u'\r');
+ return result.contains(u'"') ? result.trimmed() : result.simplified();
}
// Resolve a type (loop over aliases/typedefs), for example for base classes
+// Note: TypeAliasTemplateDecl ("using QVector<T>=QList<T>") is automatically
+// resolved by clang_getTypeDeclaration(), but it stops at
+// TypeAliasDecl / TypedefDecl.
struct TypeDeclaration
{
@@ -663,17 +678,21 @@ struct TypeDeclaration
CXCursor declaration;
};
-static TypeDeclaration resolveType(CXType type)
+static inline bool isTypeAliasDecl(const CXCursor &cursor)
+{
+ const auto kind = clang_getCursorKind(cursor);
+ return kind == CXCursor_TypeAliasDecl || kind == CXCursor_TypedefDecl;
+}
+
+static TypeDeclaration resolveBaseClassType(CXType type)
{
CXCursor decl = clang_getTypeDeclaration(type);
- if (type.kind != CXType_Unexposed) {
- while (true) {
- auto kind = clang_getCursorKind(decl);
- if (kind != CXCursor_TypeAliasDecl && kind != CXCursor_TypedefDecl)
- break;
- type = clang_getTypedefDeclUnderlyingType(decl);
- decl = clang_getTypeDeclaration(type);
- }
+ auto resolvedType = clang_getCursorType(decl);
+ if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind)
+ type = resolvedType;
+ while (isTypeAliasDecl(decl)) {
+ type = clang_getTypedefDeclUnderlyingType(decl);
+ decl = clang_getTypeDeclaration(type);
}
return {type, decl};
}
@@ -682,21 +701,11 @@ static TypeDeclaration resolveType(CXType type)
// where the cursor spelling has "struct baseClass".
std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) const
{
- const auto decl = resolveType(type);
+ const auto decl = resolveBaseClassType(type);
// Note: spelling has "struct baseClass", use type
- QString baseClassName;
- if (decl.type.kind == CXType_Unexposed) {
- // The type is unexposed when the base class is a template type alias:
- // "class QItemSelection : public QList<X>" where QList is aliased to QVector.
- // Try to resolve via code model.
- TypeInfo info = createTypeInfo(decl.type);
- auto parentScope = m_scopeStack.at(m_scopeStack.size() - 2); // Current is class.
- auto resolved = TypeInfo::resolveType(info, parentScope);
- if (resolved != info)
- baseClassName = resolved.toString();
- }
- if (baseClassName.isEmpty())
- baseClassName = getTypeName(decl.type);
+ QString baseClassName = getTypeName(decl.type);
+ if (baseClassName.startsWith(u"std::")) // Simplify "std::" types
+ baseClassName = createTypeInfo(decl.type).toString();
auto it = m_cursorClassHash.constFind(decl.declaration);
// Not found: Set unqualified name. This happens in cases like
@@ -717,11 +726,11 @@ std::pair<QString, ClassModelItem> BuilderPrivate::getBaseClass(CXType type) con
// "std::vector<T>").
const QStringList &baseScope = it.value()->scope();
if (!baseScope.isEmpty()) {
- const int lastSep = baseClassName.lastIndexOf(colonColon());
+ const int lastSep = baseClassName.lastIndexOf(u"::"_s);
if (lastSep >= 0)
- baseClassName.remove(0, lastSep + colonColon().size());
- baseClassName.prepend(colonColon());
- baseClassName.prepend(baseScope.join(colonColon()));
+ baseClassName.remove(0, lastSep + u"::"_s.size());
+ baseClassName.prepend(u"::"_s);
+ baseClassName.prepend(baseScope.join(u"::"_s));
}
return {baseClassName, it.value()};
}
@@ -735,37 +744,6 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor)
m_currentClass->addBaseClass({baseClass.first, baseClass.second, access});
}
-static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor)
-{
- Q_ASSERT(typeRefCursor.kind == CXCursor_TypeRef);
- return clang_getTypeDeclaration(clang_getCursorType(typeRefCursor));
-}
-
-// Qualify function arguments or fields that are typedef'ed from another scope:
-// enum ConversionFlag {};
-// typedef QFlags<ConversionFlag> ConversionFlags;
-// class QTextCodec {
-// enum ConversionFlag {};
-// typedef QFlags<ConversionFlag> ConversionFlags;
-// struct ConverterState {
-// explicit ConverterState(ConversionFlags);
-// ^^ qualify to QTextCodec::ConversionFlags
-// ConversionFlags m_flags;
-// ^^ ditto
-
-template <class Item> // ArgumentModelItem, VariableModelItem
-void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const
-{
- TypeInfo type = item->type();
- if (type.qualifiedName().size() == 1) { // item's type is unqualified.
- const auto it = m_cursorTypedefHash.constFind(definitionFromTypeRef(typeRefCursor));
- if (it != m_cursorTypedefHash.constEnd() && !it.value()->scope().isEmpty()) {
- type.setQualifiedName(it.value()->scope() + type.qualifiedName());
- item->setType(type);
- }
- }
-}
-
void BuilderPrivate::setFileName(const CXCursor &cursor, _CodeModelItem *item)
{
const SourceRange range = getCursorRange(cursor);
@@ -799,14 +777,48 @@ static QString baseName(QString path)
return path;
}
+const char * BuilderPrivate::specialSystemHeaderReason(BuilderPrivate::SpecialSystemHeader sh)
+{
+ static const QHash<SpecialSystemHeader, const char *> mapping {
+ {SpecialSystemHeader::OpenGL, "OpenGL"},
+ {SpecialSystemHeader::Types, "types"},
+ {SpecialSystemHeader::WhiteListed, "white listed"},
+ {SpecialSystemHeader::WhiteListedPath, "white listed path"}
+ };
+ return mapping.value(sh, "");
+}
+
bool BuilderPrivate::visitHeader(const QString &fileName) const
{
+ auto it = m_systemHeaders.find(fileName);
+ if (it == m_systemHeaders.end()) {
+ it = m_systemHeaders.insert(fileName, specialSystemHeader(fileName));
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
+ const QString &name = QDir::toNativeSeparators(fileName);
+ if (it.value() == SpecialSystemHeader::None) {
+ qCInfo(lcShiboken, "Skipping system header %s", qPrintable(name));
+ } else {
+ qCInfo(lcShiboken, "Parsing system header %s (%s)",
+ qPrintable(name), specialSystemHeaderReason(it.value()));
+ }
+ }
+ }
+ return it.value() != SpecialSystemHeader::None;
+}
+
+BuilderPrivate::SpecialSystemHeader
+ BuilderPrivate::specialSystemHeader(const QString &fileName) const
+{
// Resolve OpenGL typedefs although the header is considered a system header.
const QString baseName = clang::baseName(fileName);
if (baseName == u"gl.h"
+ || baseName == u"gl2.h"
+ || baseName == u"gl3.h"
+ || baseName == u"gl31.h"
+ || baseName == u"gl32.h"
|| baseName == u"stdint.h" // Windows: int32_t, uint32_t
- || baseName == u"stddef.h") { // size_t
- return true;
+ || baseName == u"stddef.h") { // size_t`
+ return SpecialSystemHeader::OpenGL;
}
switch (clang::platform()) {
@@ -815,32 +827,38 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const
|| baseName == u"types.h"
|| baseName == u"stdint-intn.h" // int32_t
|| baseName == u"stdint-uintn.h") { // uint32_t
- return true;
+ return SpecialSystemHeader::Types;
}
break;
case Platform::macOS:
// Parse the following system headers to get the correct typdefs for types like
// int32_t, which are used in the macOS implementation of OpenGL framework.
+ // They are installed under /Applications/Xcode.app/Contents/Developer/Platforms...
if (baseName == u"gltypes.h"
- || fileName.startsWith(u"/usr/include/_types")
- || fileName.startsWith(u"/usr/include/_types")
- || fileName.startsWith(u"/usr/include/sys/_types")) {
- return true;
+ || fileName.contains(u"/usr/include/_types")
+ || fileName.contains(u"/usr/include/sys/_types")) {
+ return SpecialSystemHeader::Types;
}
break;
default:
break;
}
- for (const auto &systemInclude : m_systemIncludes) {
- if (systemInclude == baseName)
- return true;
- }
- for (const auto &systemIncludePath : m_systemIncludePaths) {
- if (fileName.startsWith(systemIncludePath))
- return true;
+ // When building against system Qt (as it happens with yocto / Boot2Qt), the Qt headers are
+ // considered system headers by clang_Location_isInSystemHeader, and shiboken will not
+ // process them. We need to explicitly process them by checking against the list of
+ // include paths that were passed to shiboken's --force-process-system-include-paths option
+ // or specified via the <system-include> xml tag.
+ if (m_forceProcessSystemIncludes.contains(baseName))
+ return SpecialSystemHeader::WhiteListed;
+
+ if (std::any_of(m_forceProcessSystemIncludePaths.cbegin(),
+ m_forceProcessSystemIncludePaths.cend(),
+ [fileName](const QString &p) { return fileName.startsWith(p); })) {
+ return SpecialSystemHeader::WhiteListedPath;
}
- return false;
+
+ return SpecialSystemHeader::None;
}
bool Builder::visitLocation(const QString &fileName, LocationType locationType) const
@@ -848,13 +866,14 @@ bool Builder::visitLocation(const QString &fileName, LocationType locationType)
return locationType != LocationType::System || d->visitHeader(fileName);
}
-void Builder::setSystemIncludes(const QStringList &systemIncludes)
+void Builder::setForceProcessSystemIncludes(const QStringList &systemIncludes)
{
for (const auto &i : systemIncludes) {
- if (i.endsWith(u'/'))
- d->m_systemIncludePaths.append(i);
+ QFileInfo fi(i);
+ if (fi.exists() && fi.isDir())
+ d->m_forceProcessSystemIncludePaths.append(i);
else
- d->m_systemIncludes.append(i);
+ d->m_forceProcessSystemIncludes.append(i);
}
}
@@ -863,7 +882,7 @@ FileModelItem Builder::dom() const
Q_ASSERT(!d->m_scopeStack.isEmpty());
auto rootScope = d->m_scopeStack.constFirst();
rootScope->purgeClassDeclarations();
- return qSharedPointerDynamicCast<_FileModelItem>(rootScope);
+ return std::dynamic_pointer_cast<_FileModelItem>(rootScope);
}
static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope)
@@ -897,6 +916,8 @@ static NamespaceType namespaceType(const CXCursor &cursor)
static QString enumType(const CXCursor &cursor)
{
QString name = getCursorSpelling(cursor); // "enum Foo { v1, v2 };"
+ if (name.contains(u"unnamed enum")) // Clang 16.0
+ return {};
if (name.isEmpty()) {
// PYSIDE-1228: For "typedef enum { v1, v2 } Foo;", type will return
// "Foo" as expected. Care must be taken to exclude real anonymous enums.
@@ -926,7 +947,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
}
break;
case CXCursor_CXXBaseSpecifier:
- if (d->m_currentClass.isNull()) {
+ if (!d->m_currentClass) {
const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error);
qWarning() << d;
appendDiagnostic(d);
@@ -948,15 +969,15 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
|| !d->addClass(cursor, CodeModel::Class)) {
return Skip;
}
- d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets());
- d->m_scope.back() += templateBrackets();
+ d->m_currentClass->setName(d->m_currentClass->name() + "<>"_L1);
+ d->m_scope.back() += "<>"_L1;
break;
case CXCursor_EnumDecl: {
QString name = enumType(cursor);
EnumKind kind = CEnum;
if (name.isEmpty()) {
kind = AnonymousEnum;
- name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount);
+ name = "enum_"_L1 + QString::number(++d->m_anonymousEnumCount);
#if !CLANG_NO_ENUMDECL_ISSCOPED
} else if (clang_EnumDecl_isScoped(cursor) != 0) {
#else
@@ -965,17 +986,21 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
kind = EnumClass;
}
d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name));
- d->setFileName(cursor, d->m_currentEnum.data());
+ d->setFileName(cursor, d->m_currentEnum.get());
d->m_currentEnum->setScope(d->m_scope);
d->m_currentEnum->setEnumKind(kind);
- d->m_currentEnum->setSigned(isSigned(clang_getEnumDeclIntegerType(cursor).kind));
- if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull())
+ if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated)
+ d->m_currentEnum->setDeprecated(true);
+ const auto enumType = fullyResolveType(clang_getEnumDeclIntegerType(cursor));
+ d->m_currentEnum->setSigned(isSigned(enumType.kind));
+ d->m_currentEnum->setUnderlyingType(getTypeName(enumType));
+ if (std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back()))
d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
}
break;
case CXCursor_EnumConstantDecl: {
const QString name = getCursorSpelling(cursor);
- if (d->m_currentEnum.isNull()) {
+ if (!d->m_currentEnum) {
const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error);
qWarning() << d;
appendDiagnostic(d);
@@ -986,9 +1011,11 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
enumValue.setValue(clang_getEnumConstantDeclValue(cursor));
else
enumValue.setUnsignedValue(clang_getEnumConstantDeclUnsignedValue(cursor));
- EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name));
+ auto enumConstant = std::make_shared<_EnumeratorModelItem>(d->m_model, name);
enumConstant->setStringValue(d->cursorValueExpression(this, cursor));
enumConstant->setValue(enumValue);
+ if (clang_getCursorAvailability(cursor) == CXAvailability_Deprecated)
+ enumConstant->setDeprecated(true);
d->m_currentEnum->addEnumerator(enumConstant);
}
break;
@@ -1032,6 +1059,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
}
}
d->m_currentFunction = d->createFunction(cursor, CodeModel::Normal, true);
+ d->setFileName(cursor, d->m_currentFunction.get());
d->m_scopeStack.back()->addFunction(d->m_currentFunction);
break;
case CXCursor_FunctionDecl:
@@ -1039,7 +1067,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
// operators). Note: CXTranslationUnit_SkipFunctionBodies must be off for
// clang_isCursorDefinition() to work here.
if (!d->m_withinFriendDecl || clang_isCursorDefinition(cursor) != 0) {
- int scope = d->m_scopeStack.size() - 1; // enclosing class
+ auto scope = d->m_scopeStack.size() - 1; // enclosing class
if (d->m_withinFriendDecl) {
// Friend declaration: go back to namespace or file scope.
for (--scope; d->m_scopeStack.at(scope)->kind() == _CodeModelItem::Kind_Class; --scope) {
@@ -1055,8 +1083,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
if (type == NamespaceType::Anonymous)
return Skip;
const QString name = getCursorSpelling(cursor);
- const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back());
- if (parentNamespaceItem.isNull()) {
+ const auto parentNamespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(d->m_scopeStack.back());
+ if (!parentNamespaceItem) {
const QString message = msgOutOfOrder(cursor, "namespace")
+ u" (current scope: "_s + d->m_scopeStack.back()->name() + u')';
const Diagnostic d(message, cursor, CXDiagnostic_Error);
@@ -1068,7 +1096,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
// in subsequent modules.
NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name);
namespaceItem.reset(new _NamespaceModelItem(d->m_model, name));
- d->setFileName(cursor, namespaceItem.data());
+ d->setFileName(cursor, namespaceItem.get());
namespaceItem->setScope(d->m_scope);
namespaceItem->setType(type);
parentNamespaceItem->addNamespace(namespaceItem);
@@ -1078,10 +1106,12 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
case CXCursor_ParmDecl:
// Skip in case of nested CXCursor_ParmDecls in case one parameter is a function pointer
// and function pointer typedefs.
- if (d->m_currentArgument.isNull() && !d->m_currentFunction.isNull()) {
+ if (!d->m_currentArgument && d->m_currentFunction) {
const QString name = getCursorSpelling(cursor);
d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name));
- d->m_currentArgument->setType(d->createTypeInfo(cursor));
+ const auto type = clang_getCursorType(cursor);
+ d->m_currentArgument->setScopeResolution(hasScopeResolution(type));
+ d->m_currentArgument->setType(d->createTypeInfo(type));
d->m_currentFunction->addArgument(d->m_currentArgument);
QString defaultValueExpression = d->cursorValueExpression(this, cursor);
if (!defaultValueExpression.isEmpty()) {
@@ -1097,16 +1127,16 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter
? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor);
// Apply to function/member template?
- if (!d->m_currentFunction.isNull()) {
+ if (d->m_currentFunction) {
d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem);
- } else if (!d->m_currentTemplateTypeAlias.isNull()) {
+ } else if (d->m_currentTemplateTypeAlias) {
d->m_currentTemplateTypeAlias->addTemplateParameter(tItem);
- } else if (!d->m_currentClass.isNull()) { // Apply to class
+ } else if (d->m_currentClass) { // Apply to class
const QString &tplParmName = tItem->name();
if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass)
|| !insertTemplateParameterIntoClassName(tplParmName, &d->m_scope.back()))) {
- const QString message = QStringLiteral("Error inserting template parameter \"") + tplParmName
- + QStringLiteral("\" into ") + d->m_currentClass->name();
+ const QString message = "Error inserting template parameter \""_L1 + tplParmName
+ + "\" into "_L1 + d->m_currentClass->name();
const Diagnostic d(message, cursor, CXDiagnostic_Error);
qWarning() << d;
appendDiagnostic(d);
@@ -1120,7 +1150,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
d->startTemplateTypeAlias(cursor);
break;
case CXCursor_TypeAliasDecl: // May contain nested CXCursor_TemplateTypeParameter
- if (d->m_currentTemplateTypeAlias.isNull()) {
+ if (!d->m_currentTemplateTypeAlias) {
const CXType type = clang_getCanonicalType(clang_getCursorType(cursor));
if (type.kind > CXType_Unexposed)
d->addTypeDef(cursor, type);
@@ -1148,31 +1178,23 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
d->m_usingTypeRef = getCursorSpelling(cursor);
break;
case CXCursor_TypeRef:
- if (!d->m_currentFunction.isNull()) {
- if (d->m_currentArgument.isNull())
- d->qualifyTypeDef(cursor, d->m_currentFunction); // return type
- else
- d->qualifyTypeDef(cursor, d->m_currentArgument);
- } else if (!d->m_currentField.isNull()) {
- d->qualifyTypeDef(cursor, d->m_currentField);
- } else if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) {
+ if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty())
d->m_usingTypeRef = d->getBaseClass(clang_getCursorType(cursor)).first;
- }
break;
case CXCursor_CXXFinalAttr:
- if (!d->m_currentFunction.isNull())
- d->m_currentFunction->setFinal(true);
- else if (!d->m_currentClass.isNull())
+ if (d->m_currentFunction)
+ d->m_currentFunction->setAttribute(FunctionAttribute::Final);
+ else if (d->m_currentClass)
d->m_currentClass->setFinal(true);
break;
case CXCursor_CXXOverrideAttr:
- if (!d->m_currentFunction.isNull())
- d->m_currentFunction->setOverride(true);
+ if (d->m_currentFunction)
+ d->m_currentFunction->setAttribute(FunctionAttribute::Override);
break;
case CXCursor_StaticAssert:
// Check for Q_PROPERTY() (see PySide6/global.h.in for an explanation
// how it is defined, and qdoc).
- if (clang_isDeclaration(cursor.kind) && !d->m_currentClass.isNull()) {
+ if (clang_isDeclaration(cursor.kind) && d->m_currentClass) {
auto snippet = getCodeSnippet(cursor);
const auto length = snippet.size();
if (length > 12 && *snippet.rbegin() == ')'
@@ -1184,7 +1206,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
break;
// UsingDeclaration: consists of a TypeRef (base) and OverloadedDeclRef (member name)
case CXCursor_UsingDeclaration:
- if (!d->m_currentClass.isNull())
+ if (d->m_currentClass)
d->m_withinUsingDeclaration = true;
break;
case CXCursor_OverloadedDeclRef:
@@ -1212,51 +1234,51 @@ bool Builder::endToken(const CXCursor &cursor)
case CXCursor_ClassTemplatePartialSpecialization:
d->popScope();
// Continue in outer class after leaving inner class?
- if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()))
+ if (auto lastClass = std::dynamic_pointer_cast<_ClassModelItem>(d->m_scopeStack.back()))
d->m_currentClass = lastClass;
else
- d->m_currentClass.clear();
+ d->m_currentClass.reset();
d->m_currentFunctionType = CodeModel::Normal;
break;
case CXCursor_EnumDecl:
- if (!d->m_currentEnum.isNull())
+ if (d->m_currentEnum)
d->m_scopeStack.back()->addEnum(d->m_currentEnum);
- d->m_currentEnum.clear();
+ d->m_currentEnum.reset();
break;
case CXCursor_FriendDecl:
d->m_withinFriendDecl = false;
break;
case CXCursor_VarDecl:
case CXCursor_FieldDecl:
- d->m_currentField.clear();
+ d->m_currentField.reset();
break;
case CXCursor_Constructor:
d->qualifyConstructor(cursor);
- if (!d->m_currentFunction.isNull()) {
+ if (d->m_currentFunction) {
d->m_currentFunction->_determineType();
- d->m_currentFunction.clear();
+ d->m_currentFunction.reset();
}
break;
case CXCursor_Destructor:
case CXCursor_CXXMethod:
case CXCursor_FunctionDecl:
case CXCursor_FunctionTemplate:
- if (!d->m_currentFunction.isNull()) {
+ if (d->m_currentFunction) {
d->m_currentFunction->_determineType();
- d->m_currentFunction.clear();
+ d->m_currentFunction.reset();
}
break;
case CXCursor_ConversionFunction:
- if (!d->m_currentFunction.isNull()) {
+ if (d->m_currentFunction) {
d->m_currentFunction->setFunctionType(CodeModel::ConversionOperator);
- d->m_currentFunction.clear();
+ d->m_currentFunction.reset();
}
break;
case CXCursor_Namespace:
d->popScope();
break;
case CXCursor_ParmDecl:
- d->m_currentArgument.clear();
+ d->m_currentArgument.reset();
break;
case CXCursor_TypeAliasTemplateDecl:
d->m_currentTemplateTypeAlias.reset();
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h
index 56b6347d5..b2ec6d304 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.h
@@ -14,12 +14,12 @@ class BuilderPrivate;
class Builder : public BaseVisitor {
public:
- Q_DISABLE_COPY(Builder)
+ Q_DISABLE_COPY_MOVE(Builder)
Builder();
~Builder();
- void setSystemIncludes(const QStringList &systemIncludes);
+ void setForceProcessSystemIncludes(const QStringList &systemIncludes);
bool visitLocation(const QString &fileName, LocationType locationType) const override;
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp
index 93618cf0f..3c002da9c 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.cpp
@@ -7,8 +7,6 @@
#include <QtCore/QDebug>
#include <QtCore/QString>
-#include <string.h>
-
#ifndef QT_NO_DEBUG_STREAM
#ifdef Q_OS_WIN
@@ -19,7 +17,7 @@ const char pathSep = '/';
static const char *baseName(const char *fileName)
{
- const char *b = strrchr(fileName, pathSep);
+ const char *b = std::strrchr(fileName, pathSep);
return b ? b + 1 : fileName;
}
@@ -49,59 +47,99 @@ QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac)
return s;
}
-QDebug operator<<(QDebug s, const CXType &t)
+struct formatCXTypeName
+{
+ explicit formatCXTypeName(const CXType &type) : m_type(type) {}
+
+ const CXType &m_type;
+};
+
+QDebug operator<<(QDebug debug, const formatCXTypeName &ft)
{
- CXString typeSpelling = clang_getTypeSpelling(t);
- s << typeSpelling;
+ CXString typeSpelling = clang_getTypeSpelling(ft.m_type);
+ debug << typeSpelling;
clang_disposeString(typeSpelling);
- return s;
+ return debug;
}
-QDebug operator<<(QDebug s, const CXCursor &cursor)
+QDebug operator<<(QDebug debug, const CXType &type)
{
- QDebugStateSaver saver(s);
- s.nospace();
- s.noquote();
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug.noquote();
+ debug << "CXType(";
+ if (type.kind == CXType_Invalid) {
+ debug << "invalid)";
+ return debug;
+ }
+
+ debug << type.kind;
+ switch (type.kind) {
+ case CXType_Unexposed:
+ debug << " [unexposed]";
+ break;
+ case CXType_Elaborated:
+ debug << " [elaborated]";
+ break;
+ default:
+ break;
+ }
+ debug << ", " << formatCXTypeName(type) << ')';
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const CXCursor &cursor)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug.noquote();
const CXCursorKind kind = clang_getCursorKind(cursor);
- s << kind;
- if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid)
- return s;
+ debug << "CXCursor(";
+ if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) {
+ debug << "invalid)";
+ return debug;
+ }
+
+ const QString cursorSpelling = clang::getCursorSpelling(cursor);
+ debug << '"' << cursorSpelling << '"';
+ CXString cursorDisplay = clang_getCursorDisplayName(cursor);
+ if (const char *dpy = clang_getCString(cursorDisplay)) {
+ const QString display = QString::fromUtf8(dpy);
+ if (display != cursorSpelling)
+ debug << ", display=\"" << dpy << '"';
+ }
+ clang_disposeString(cursorDisplay);
+
+ debug << ", kind=" << kind;
+
const CXType type = clang_getCursorType(cursor);
switch (kind) {
case CXCursor_CXXAccessSpecifier:
- s << ' ' << clang_getCXXAccessSpecifier(cursor);
+ debug << ", " << clang_getCXXAccessSpecifier(cursor);
break;
case CXCursor_CXXBaseSpecifier:
- s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"';
+ debug << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"';
break;
case CXCursor_CXXMethod:
case CXCursor_FunctionDecl:
case CXCursor_ConversionFunction:
- s << ", result type=\"" << clang_getCursorResultType(cursor) << '"';
+ debug << ", result type=\""
+ << formatCXTypeName(clang_getCursorResultType(cursor)) << '"';
break;
case CXCursor_TypedefDecl:
- s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"';
+ debug << ", underlyingType=\""
+ << formatCXTypeName(clang_getTypedefDeclUnderlyingType(cursor)) << '"';
break;
default:
break;
}
- if (type.kind != CXType_Invalid)
- s << ", type=\"" << type << '"';
+ debug << ", type=\"" << formatCXTypeName(type) << '"';
if (clang_Cursor_hasAttrs(cursor))
- s << ", [attrs]";
+ debug << ", [attrs]";
- const QString cursorSpelling = clang::getCursorSpelling(cursor);
- if (!cursorSpelling.isEmpty())
- s << ", spelling=\"" << cursorSpelling << '"';
- CXString cursorDisplay = clang_getCursorDisplayName(cursor);
- if (const char *dpy = clang_getCString(cursorDisplay)) {
- const QString display = QString::fromUtf8(dpy);
- if (display != cursorSpelling)
- s << ", display=\"" << dpy << '"';
- }
- clang_disposeString(cursorDisplay);
- return s;
+ debug << ')';
+ return debug;
}
QDebug operator<<(QDebug s, const CXSourceLocation &location)
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h
index 3a1b91e1a..7aac8a575 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangdebugutils.h
@@ -4,7 +4,7 @@
#ifndef CLANGDEBUGUTILS_H
#define CLANGDEBUGUTILS_H
-#include <QtCore/QtGlobal>
+#include <QtCore/qtclasshelpermacros.h>
#include <clang-c/Index.h>
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
index 4549d62a0..da6930476 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.cpp
@@ -13,6 +13,8 @@
#include <QtCore/QScopedArrayPointer>
#include <QtCore/QString>
+using namespace Qt::StringLiterals;
+
namespace clang {
QString SourceFileCache::getFileName(CXFile file)
@@ -39,7 +41,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor,
if (range.first.file != range.second.file) {
if (errorMessage)
- *errorMessage = QStringLiteral("Range spans several files");
+ *errorMessage = "Range spans several files"_L1;
return std::string_view(empty, 0);
}
@@ -48,7 +50,7 @@ std::string_view SourceFileCache::getCodeSnippet(const CXCursor &cursor,
const QString fileName = getFileName(range.first.file);
if (fileName.isEmpty()) {
if (errorMessage)
- *errorMessage = QStringLiteral("Range has no file");
+ *errorMessage = "Range has no file"_L1;
return std::string_view(empty, 0);
}
QFile file(fileName);
@@ -213,9 +215,9 @@ static QByteArray msgCreateTranslationUnit(const QByteArrayList &clangArgs, unsi
{
QByteArray result = "clang_parseTranslationUnit2(0x";
result += QByteArray::number(flags, 16);
- const int count = clangArgs.size();
+ const auto count = clangArgs.size();
result += ", cmd[" + QByteArray::number(count) + "]=";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
const QByteArray &arg = clangArgs.at(i);
if (i)
result += ' ';
@@ -308,7 +310,7 @@ bool parse(const QByteArrayList &clangArgs, bool addCompilerSupportArguments,
debug.nospace();
debug << "Errors in "
<< QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n";
- for (const Diagnostic &diagnostic : qAsConst(diagnostics))
+ for (const Diagnostic &diagnostic : std::as_const(diagnostics))
debug << diagnostic << '\n';
}
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h
index 3abbece24..4a46248e4 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangparser.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangparser.h
@@ -8,11 +8,11 @@
#include <QtCore/QByteArrayList>
#include <QtCore/QHash>
-#include <QtCore/QPair>
#include <QtCore/QString>
#include <QtCore/QList>
#include <string_view>
+#include <utility>
namespace clang {
@@ -40,7 +40,7 @@ enum class LocationType
};
class BaseVisitor {
- Q_DISABLE_COPY(BaseVisitor)
+ Q_DISABLE_COPY_MOVE(BaseVisitor)
public:
using Diagnostics = QList<Diagnostic>;
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp
index 3d5b04fd2..1651e09ec 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.cpp
@@ -8,38 +8,33 @@
#include <QtCore/QHashFunctions>
#include <QtCore/QProcess>
-bool operator==(const CXCursor &c1, const CXCursor &c2)
+#include <string_view>
+
+bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept
{
return c1.kind == c2.kind
&& c1.xdata == c2.xdata
&& std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data);
}
-size_t qHash(const CXCursor &c, size_t seed)
+size_t qHash(const CXCursor &c, size_t seed) noexcept
{
- return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0])
- ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed;
+ return qHashMulti(seed, c.kind, c.xdata, c.data[0], c.data[1], c.data[2]);
}
-bool operator==(const CXType &t1, const CXType &t2)
+bool operator==(const CXType &t1, const CXType &t2) noexcept
{
return t1.kind == t2.kind && t1.data[0] == t2.data[0]
&& t1.data[1] == t2.data[1];
}
-size_t qHash(const CXType &ct, size_t seed)
+size_t qHash(const CXType &ct, size_t seed) noexcept
{
- return size_t(ct.kind) ^ size_t(0xFFFFFFFF & quintptr(ct.data[0]))
- ^ size_t(0xFFFFFFFF & quintptr(ct.data[1])) ^ seed;
+ return qHashMulti(seed, ct.kind, ct.data[0], ct.data[1]);
}
namespace clang {
-bool SourceLocation::equals(const SourceLocation &rhs) const
-{
- return file == rhs.file && offset == rhs.offset;
-}
-
SourceLocation getExpansionLocation(const CXSourceLocation &location)
{
SourceLocation result;
@@ -77,8 +72,8 @@ CXString getFileNameFromLocation(const CXSourceLocation &location)
SourceRange getCursorRange(const CXCursor &cursor)
{
const CXSourceRange extent = clang_getCursorExtent(cursor);
- return qMakePair(getExpansionLocation(clang_getRangeStart(extent)),
- getExpansionLocation(clang_getRangeEnd(extent)));
+ return std::make_pair(getExpansionLocation(clang_getRangeStart(extent)),
+ getExpansionLocation(clang_getRangeEnd(extent)));
}
QString getCursorKindName(CXCursorKind cursorKind)
@@ -105,6 +100,43 @@ QString getCursorDisplayName(const CXCursor &cursor)
return result;
}
+static inline bool isBuiltinType(CXTypeKind kind)
+{
+ return kind >= CXType_FirstBuiltin && kind <= CXType_LastBuiltin;
+}
+
+// Resolve elaborated types occurring with clang 16
+static CXType resolveElaboratedType(const CXType &type)
+{
+ if (!isBuiltinType(type.kind)) {
+ CXCursor decl = clang_getTypeDeclaration(type);
+ auto resolvedType = clang_getCursorType(decl);
+ if (resolvedType.kind != CXType_Invalid && resolvedType.kind != type.kind)
+ return resolvedType;
+ }
+ return type;
+}
+
+// Resolve typedefs
+static CXType resolveTypedef(const CXType &type)
+{
+ auto result = type;
+ while (result.kind == CXType_Typedef) {
+ auto decl = clang_getTypeDeclaration(result);
+ auto resolved = clang_getTypedefDeclUnderlyingType(decl);
+ if (resolved.kind == CXType_Invalid)
+ break;
+ result = resolved;
+ }
+ return result;
+}
+
+// Fully resolve a type from elaborated & typedefs
+CXType fullyResolveType(const CXType &type)
+{
+ return resolveTypedef(resolveElaboratedType(type));
+}
+
QString getTypeName(const CXType &type)
{
CXString typeSpelling = clang_getTypeSpelling(type);
@@ -113,6 +145,23 @@ QString getTypeName(const CXType &type)
return result;
}
+// Quick check for "::Type"
+bool hasScopeResolution(const CXType &type)
+{
+ CXString typeSpelling = clang_getTypeSpelling(type);
+ std::string_view spelling = clang_getCString(typeSpelling);
+ const bool result = spelling.compare(0, 2, "::") == 0
+ || spelling.find(" ::") != std::string::npos;
+ clang_disposeString(typeSpelling);
+ return result;
+}
+
+// Resolve elaborated types occurring with clang 16
+QString getResolvedTypeName(const CXType &type)
+{
+ return getTypeName(resolveElaboratedType(type));
+}
+
Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s)
: message(m), source(Other), severity(s)
{
@@ -166,16 +215,17 @@ QList<Diagnostic> getDiagnostics(CXTranslationUnit tu)
return result;
}
-QPair<int, int> parseTemplateArgumentList(const QString &l,
- const TemplateArgumentHandler &handler,
- int from)
+std::pair<qsizetype, qsizetype>
+ parseTemplateArgumentList(const QString &l,
+ const TemplateArgumentHandler &handler,
+ qsizetype from)
{
- const int ltPos = l.indexOf(u'<', from);
+ const auto ltPos = l.indexOf(u'<', from);
if (ltPos == - 1)
- return qMakePair(-1, -1);
- int startPos = ltPos + 1;
+ return std::make_pair(-1, -1);
+ auto startPos = ltPos + 1;
int level = 1;
- for (int p = startPos, end = l.size(); p < end; ) {
+ for (qsizetype p = startPos, end = l.size(); p < end; ) {
const char c = l.at(p).toLatin1();
switch (c) {
case ',':
@@ -184,7 +234,7 @@ QPair<int, int> parseTemplateArgumentList(const QString &l,
++p;
if (c == '>') {
if (--level == 0)
- return qMakePair(ltPos, p);
+ return std::make_pair(ltPos, p);
// Skip over next ',': "a<b<c,d>,e>"
for (; p < end && (l.at(p).isSpace() || l.at(p) == u','); ++p) {}
}
@@ -200,7 +250,7 @@ QPair<int, int> parseTemplateArgumentList(const QString &l,
break;
}
}
- return qMakePair(-1, -1);
+ return std::make_pair(-1, -1);
}
CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds)
@@ -256,9 +306,9 @@ QDebug operator<<(QDebug s, const Diagnostic &d)
if (d.source != Diagnostic::Clang)
s << " [other]";
- if (const int childMessagesCount = d.childMessages.size()) {
+ if (const auto childMessagesCount = d.childMessages.size()) {
s << '\n';
- for (int i = 0; i < childMessagesCount; ++i)
+ for (qsizetype i = 0; i < childMessagesCount; ++i)
s << " " << d.childMessages.at(i) << '\n';
}
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h
index c1d6be446..fbbf95f1b 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangutils.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangutils.h
@@ -5,20 +5,21 @@
#define CLANGUTILS_H
#include <clang-c/Index.h>
-#include <QtCore/QPair>
#include <QtCore/QString>
#include <QtCore/QStringList>
+#include <QtCore/QtCompare>
#include <QtCore/QList>
#include <functional>
+#include <utility>
QT_FORWARD_DECLARE_CLASS(QDebug)
-bool operator==(const CXCursor &c1, const CXCursor &c2);
-size_t qHash(const CXCursor &c, size_t seed = 0);
+bool operator==(const CXCursor &c1, const CXCursor &c2) noexcept;
+size_t qHash(const CXCursor &c, size_t seed = 0) noexcept;
-bool operator==(const CXType &t1, const CXType &t2);
-size_t qHash(const CXType &ct, size_t seed);
+bool operator==(const CXType &t1, const CXType &t2) noexcept;
+size_t qHash(const CXType &ct, size_t seed = 0) noexcept;
namespace clang {
@@ -26,6 +27,9 @@ QString getCursorKindName(CXCursorKind cursorKind);
QString getCursorSpelling(const CXCursor &cursor);
QString getCursorDisplayName(const CXCursor &cursor);
QString getTypeName(const CXType &type);
+bool hasScopeResolution(const CXType &type);
+CXType fullyResolveType(const CXType &type);
+QString getResolvedTypeName(const CXType &type);
inline QString getCursorTypeName(const CXCursor &cursor)
{ return getTypeName(clang_getCursorType(cursor)); }
inline QString getCursorResultTypeName(const CXCursor &cursor)
@@ -46,17 +50,18 @@ struct SourceLocation
unsigned line = 0;
unsigned column = 0;
unsigned offset = 0;
-};
-
-inline bool operator==(const SourceLocation &l1, const SourceLocation &l2)
-{ return l1.equals(l2); }
-inline bool operator!=(const SourceLocation &l1, const SourceLocation &l2)
-{ return !l1.equals(l2); }
+ friend constexpr bool comparesEqual(const SourceLocation &lhs,
+ const SourceLocation &rhs) noexcept
+ {
+ return lhs.file == rhs.file && lhs.offset == rhs.offset;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(SourceLocation)
+};
SourceLocation getExpansionLocation(const CXSourceLocation &location);
-using SourceRange =QPair<SourceLocation, SourceLocation>;
+using SourceRange = std::pair<SourceLocation, SourceLocation>;
SourceLocation getCursorLocation(const CXCursor &cursor);
CXString getFileNameFromLocation(const CXSourceLocation &location);
@@ -89,9 +94,10 @@ CXDiagnosticSeverity maxSeverity(const QList<Diagnostic> &ds);
// with each match (level and string). Return begin and end of the list.
using TemplateArgumentHandler = std::function<void (int, QStringView)>;
-QPair<int, int> parseTemplateArgumentList(const QString &l,
- const TemplateArgumentHandler &handler,
- int from = 0);
+std::pair<qsizetype, qsizetype>
+ parseTemplateArgumentList(const QString &l,
+ const TemplateArgumentHandler &handler,
+ qsizetype from = 0);
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug, const SourceLocation &);
diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
index 9b9e036f4..4c13b141f 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
@@ -3,6 +3,7 @@
#include "compilersupport.h"
#include "header_paths.h"
+#include "clangutils.h"
#include <reporthandler.h>
@@ -19,7 +20,6 @@
#include <clang-c/Index.h>
-#include <string.h>
#include <algorithm>
#include <iterator>
@@ -43,6 +43,32 @@ static Compiler _compiler =
Compiler compiler() { return _compiler; }
+bool setCompiler(const QString &name)
+{
+ bool result = true;
+ if (name == u"msvc")
+ _compiler = Compiler::Msvc;
+ else if (name == u"g++")
+ _compiler = Compiler::Gpp;
+ else if (name == u"clang")
+ _compiler = Compiler::Clang;
+ else
+ result = false;
+ return result;
+}
+
+QString _compilerPath; // Pre-defined compiler path (from command line)
+
+const QString &compilerPath()
+{
+ return _compilerPath;
+}
+
+void setCompilerPath(const QString &name)
+{
+ _compilerPath = name;
+}
+
static Platform _platform =
#if defined (Q_OS_DARWIN)
Platform::macOS;
@@ -54,6 +80,26 @@ static Platform _platform =
Platform platform() { return _platform; }
+bool setPlatform(const QString &name)
+{
+ bool result = true;
+ if (name == u"windows")
+ _platform = Platform::Windows;
+ else if (name == u"darwin")
+ _platform = Platform::macOS;
+ else if (name == u"unix")
+ _platform = Platform::Unix;
+ else
+ result = false;
+ return result;
+}
+
+// 3/2024: Use a recent MSVC2022 for libclang 18.X
+static QByteArray msvcCompatVersion()
+{
+ return libClangVersion() >= QVersionNumber(0, 64) ? "19.39"_ba : "19.26"_ba;
+}
+
static bool runProcess(const QString &program, const QStringList &arguments,
QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr)
{
@@ -132,15 +178,20 @@ static void filterHomebrewHeaderPaths(HeaderPaths &headerPaths)
static HeaderPaths gppInternalIncludePaths(const QString &compiler)
{
HeaderPaths result;
- QStringList arguments;
- arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++")
- << QStringLiteral("-") << QStringLiteral("-v");
+ QStringList arguments{u"-E"_s, u"-x"_s, u"c++"_s, u"-"_s, u"-v"_s};
QByteArray stdOut;
QByteArray stdErr;
if (!runProcess(compiler, arguments, &stdOut, &stdErr))
return result;
const QByteArrayList stdErrLines = stdErr.split('\n');
bool isIncludeDir = false;
+
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug))
+ qCInfo(lcShiboken()).noquote().nospace()
+ << "gppInternalIncludePaths:\n compiler: " << compiler
+ << "\n stdOut: " << stdOut
+ << "\n stdErr: " << stdErr;
+
for (const QByteArray &line : stdErrLines) {
if (isIncludeDir) {
if (line.startsWith(QByteArrayLiteral("End of search list"))) {
@@ -202,6 +253,23 @@ static bool needsClangBuiltinIncludes()
return platform() != Platform::macOS;
}
+static QString queryLlvmConfigDir(const QString &arg)
+{
+ static const QString llvmConfig = QStandardPaths::findExecutable(u"llvm-config"_s);
+ if (llvmConfig.isEmpty())
+ return {};
+ QByteArray stdOut;
+ if (!runProcess(llvmConfig, QStringList{arg}, &stdOut))
+ return {};
+ const QString path = QFile::decodeName(stdOut.trimmed());
+ if (!QFileInfo::exists(path)) {
+ qWarning(R"(%s: "%s" as returned by llvm-config "%s" does not exist.)",
+ __FUNCTION__, qPrintable(QDir::toNativeSeparators(path)), qPrintable(arg));
+ return {};
+ }
+ return path;
+}
+
static QString findClangLibDir()
{
for (const char *envVar : {"LLVM_INSTALL_DIR", "CLANG_INSTALL_DIR"}) {
@@ -212,18 +280,7 @@ static QString findClangLibDir()
qWarning("%s: %s as pointed to by %s does not exist.", __FUNCTION__, qPrintable(path), envVar);
}
}
- const QString llvmConfig =
- QStandardPaths::findExecutable(u"llvm-config"_s);
- if (!llvmConfig.isEmpty()) {
- QByteArray stdOut;
- if (runProcess(llvmConfig, QStringList{u"--libdir"_s}, &stdOut)) {
- const QString path = QFile::decodeName(stdOut.trimmed());
- if (QFileInfo::exists(path))
- return path;
- qWarning("%s: %s as returned by llvm-config does not exist.", __FUNCTION__, qPrintable(path));
- }
- }
- return QString();
+ return queryLlvmConfigDir(u"--libdir"_s);
}
static QString findClangBuiltInIncludesDir()
@@ -250,20 +307,44 @@ static QString findClangBuiltInIncludesDir()
}
}
if (!candidate.isEmpty())
- return candidate + QStringLiteral("/include");
+ return candidate + "/include"_L1;
}
- return QString();
+ return queryLlvmConfigDir(u"--includedir"_s);
}
-static QString compilerFromCMake(const QString &defaultCompiler)
+QString compilerFromCMake()
{
-// Added !defined(Q_OS_DARWIN) due to PYSIDE-1032
- QString result = defaultCompiler;
- if (platform() != Platform::macOS)
#ifdef CMAKE_CXX_COMPILER
- result = QString::fromLocal8Bit(CMAKE_CXX_COMPILER);
+ return QString::fromLocal8Bit(CMAKE_CXX_COMPILER);
+#else
+ return {};
#endif
- return result;
+}
+
+// Return a compiler suitable for determining the internal include paths
+static QString compilerFromCMake(const QString &defaultCompiler)
+{
+ if (!compilerPath().isEmpty())
+ return compilerPath();
+ // Exclude macOS since cmakeCompiler returns the full path instead of the
+ // /usr/bin/clang shim, which results in the default SDK sysroot path
+ // missing (PYSIDE-1032)
+ if (platform() == Platform::macOS)
+ return defaultCompiler;
+ QString cmakeCompiler = compilerFromCMake();
+ if (cmakeCompiler.isEmpty())
+ return defaultCompiler;
+ QFileInfo fi(cmakeCompiler);
+ // Should be absolute by default, but a user may specify -DCMAKE_CXX_COMPILER=cl.exe
+ if (fi.isRelative())
+ return cmakeCompiler;
+ if (fi.exists())
+ return fi.absoluteFilePath();
+ // The compiler may not exist in case something like icecream or
+ // a non-standard-path was used on the build machine. Check
+ // the executable.
+ cmakeCompiler = QStandardPaths::findExecutable(fi.fileName());
+ return cmakeCompiler.isEmpty() ? defaultCompiler : cmakeCompiler;
}
static void appendClangBuiltinIncludes(HeaderPaths *p)
@@ -275,7 +356,8 @@ static void appendClangBuiltinIncludes(HeaderPaths *p)
"(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR "
" nor running llvm-config). This may lead to parse errors.");
} else {
- qCInfo(lcShiboken, "CLANG builtins includes directory: %s",
+ qCInfo(lcShiboken, "CLANG v%d.%d, builtins includes directory: %s",
+ CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR,
qPrintable(clangBuiltinIncludesDir));
p->append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir),
HeaderType::System});
@@ -289,9 +371,10 @@ QByteArrayList emulatedCompilerOptions()
HeaderPaths headerPaths;
switch (compiler()) {
case Compiler::Msvc:
- result.append(QByteArrayLiteral("-fms-compatibility-version=19.26.28806"));
+ result.append("-fms-compatibility-version="_ba + msvcCompatVersion());
result.append(QByteArrayLiteral("-fdelayed-template-parsing"));
result.append(QByteArrayLiteral("-Wno-microsoft-enum-value"));
+ result.append("/Zc:__cplusplus"_ba);
// Fix yvals_core.h: STL1000: Unexpected compiler version, expected Clang 7 or newer (MSVC2017 update)
result.append(QByteArrayLiteral("-D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH"));
if (needsClangBuiltinIncludes())
@@ -304,6 +387,14 @@ QByteArrayList emulatedCompilerOptions()
case Compiler::Gpp:
if (needsClangBuiltinIncludes())
appendClangBuiltinIncludes(&headerPaths);
+
+ // Append the c++ include paths since Clang is unable to find
+ // <type_traits> etc (g++ 11.3).
+ const HeaderPaths gppPaths = gppInternalIncludePaths(compilerFromCMake(u"g++"_s));
+ for (const HeaderPath &h : gppPaths) {
+ if (h.path.contains("c++") || h.path.contains("sysroot"))
+ headerPaths.append(h);
+ }
break;
}
diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
index 24d109cac..462e8f205 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
+++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.h
@@ -7,6 +7,7 @@
#include <QtCore/QByteArrayList>
QT_FORWARD_DECLARE_CLASS(QVersionNumber)
+QT_FORWARD_DECLARE_CLASS(QString)
enum class LanguageLevel {
Default,
@@ -41,7 +42,15 @@ LanguageLevel languageLevelFromOption(const char *);
QByteArrayList detectVulkan();
Compiler compiler();
+bool setCompiler(const QString &name);
+
+QString compilerFromCMake();
+
+const QString &compilerPath();
+void setCompilerPath(const QString &name);
+
Platform platform();
+bool setPlatform(const QString &name);
} // namespace clang
#endif // COMPILERSUPPORT_H
diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
index 4636072ea..637e4a422 100644
--- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp
+++ b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
@@ -3,6 +3,7 @@
#include "classdocumentation.h"
#include "messages.h"
+#include "debughelpers_p.h"
#include <QtCore/QDebug>
#include <QtCore/QBuffer>
@@ -13,6 +14,8 @@
#include <algorithm>
+using namespace Qt::StringLiterals;
+
// Sort functions by name and argument count
static bool functionDocumentationLessThan(const FunctionDocumentation &f1,
const FunctionDocumentation &f2)
@@ -80,59 +83,67 @@ qsizetype ClassDocumentation::indexOfProperty(const QString &name) const
return -1;
}
-enum class WebXmlTag
+enum class WebXmlCodeTag
{
- Class, Description, Enum, Function, Parameter, Property, Typedef, Other
+ Class, Description, Enum, Function, Header, Parameter, Property, Typedef, Other
};
-static WebXmlTag tag(QStringView name)
+static WebXmlCodeTag tag(QStringView name)
{
if (name == u"class" || name == u"namespace")
- return WebXmlTag::Class;
+ return WebXmlCodeTag::Class;
if (name == u"enum")
- return WebXmlTag::Enum;
+ return WebXmlCodeTag::Enum;
if (name == u"function")
- return WebXmlTag::Function;
+ return WebXmlCodeTag::Function;
if (name == u"description")
- return WebXmlTag::Description;
+ return WebXmlCodeTag::Description;
+ if (name == u"header")
+ return WebXmlCodeTag::Header;
if (name == u"parameter")
- return WebXmlTag::Parameter;
+ return WebXmlCodeTag::Parameter;
if (name == u"property")
- return WebXmlTag::Property;
+ return WebXmlCodeTag::Property;
if (name == u"typedef")
- return WebXmlTag::Typedef;
- return WebXmlTag::Other;
+ return WebXmlCodeTag::Typedef;
+ return WebXmlCodeTag::Other;
}
-static void parseWebXmlElement(WebXmlTag tag, const QXmlStreamAttributes &attributes,
+static void parseWebXmlElement(WebXmlCodeTag tag, const QXmlStreamAttributes &attributes,
ClassDocumentation *cd)
{
switch (tag) {
- case WebXmlTag::Class:
- cd->name = attributes.value(u"name"_qs).toString();
+ case WebXmlCodeTag::Class:
+ cd->name = attributes.value(u"name"_s).toString();
+ cd->type = ClassDocumentation::Class;
+ break;
+ case WebXmlCodeTag::Header:
+ cd->name = attributes.value(u"name"_s).toString();
+ cd->type = ClassDocumentation::Header;
break;
- case WebXmlTag::Enum: {
+ case WebXmlCodeTag::Enum: {
EnumDocumentation ed;
- ed.name = attributes.value(u"name"_qs).toString();
+ ed.name = attributes.value(u"name"_s).toString();
cd->enums.append(ed);
}
break;
- case WebXmlTag::Function: {
+ case WebXmlCodeTag::Function: {
FunctionDocumentation fd;
- fd.name = attributes.value(u"name"_qs).toString();
- fd.signature = attributes.value(u"signature"_qs).toString();
- fd.returnType = attributes.value(u"type"_qs).toString();
- fd.constant = attributes.value(u"const"_qs) == u"true";
+ fd.name = attributes.value(u"name"_s).toString();
+ fd.signature = attributes.value(u"signature"_s).toString();
+ fd.returnType = attributes.value(u"type"_s).toString();
+ fd.constant = attributes.value(u"const"_s) == u"true";
cd->functions.append(fd);
}
break;
- case WebXmlTag::Parameter:
+ case WebXmlCodeTag::Parameter:
Q_ASSERT(!cd->functions.isEmpty());
- cd->functions.last().parameters.append(attributes.value(u"type"_qs).toString());
+ cd->functions.last().parameters.append(attributes.value(u"type"_s).toString());
break;
- case WebXmlTag::Property: {
+ case WebXmlCodeTag::Property: {
PropertyDocumentation pd;
- pd.name = attributes.value(u"name"_qs).toString();
+ pd.name = attributes.value(u"name"_s).toString();
+ pd.brief = attributes.value(u"brief"_s).toString();
cd->properties.append(pd);
}
break;
@@ -181,17 +192,17 @@ static QString msgXmlError(const QString &fileName, const QXmlStreamReader &read
return result;
}
-ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage)
+std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage)
{
ClassDocumentation result;
QFile file(fileName);
if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) {
*errorMessage = msgCannotOpenForReading(file);
- return result;
+ return std::nullopt;
}
- WebXmlTag lastTag = WebXmlTag::Other;
+ WebXmlCodeTag lastTag = WebXmlCodeTag::Other;
QXmlStreamReader reader(&file);
while (!reader.atEnd()) {
switch (reader.readNext()) {
@@ -199,26 +210,27 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage)
const auto currentTag = tag(reader.name());
parseWebXmlElement(currentTag, reader.attributes(), &result);
switch (currentTag) { // Store relevant tags in lastTag
- case WebXmlTag::Class:
- case WebXmlTag::Function:
- case WebXmlTag::Enum:
- case WebXmlTag::Property:
- case WebXmlTag::Typedef:
+ case WebXmlCodeTag::Class:
+ case WebXmlCodeTag::Function:
+ case WebXmlCodeTag::Enum:
+ case WebXmlCodeTag::Header:
+ case WebXmlCodeTag::Property:
+ case WebXmlCodeTag::Typedef:
lastTag = currentTag;
break;
- case WebXmlTag::Description: { // Append the description to the element
+ case WebXmlCodeTag::Description: { // Append the description to the element
QString *target = nullptr;
switch (lastTag) {
- case WebXmlTag::Class:
+ case WebXmlCodeTag::Class:
target = &result.description;
break;
- case WebXmlTag::Function:
+ case WebXmlCodeTag::Function:
target = &result.functions.last().description;
break;
- case WebXmlTag::Enum:
+ case WebXmlCodeTag::Enum:
target = &result.enums.last().description;
break;
- case WebXmlTag::Property:
+ case WebXmlCodeTag::Property:
target = &result.properties.last().description;
default:
break;
@@ -238,7 +250,7 @@ ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage)
if (reader.error() != QXmlStreamReader::NoError) {
*errorMessage= msgXmlError(fileName, reader);
- return {};
+ return std::nullopt;
}
sortDocumentation(&result);
@@ -274,21 +286,6 @@ QString webXmlModuleDescription(const QString &fileName, QString *errorMessage)
return result;
}
-// Debug helpers
-template <class T>
-static void formatList(QDebug &debug, const char *title, const QList<T> &l)
-{
- if (const qsizetype size = l.size()) {
- debug << title << '[' << size << "]=(";
- for (qsizetype i = 0; i < size; ++i) {
- if (i)
- debug << ", ";
- debug << l.at(i);
- }
- debug << ')';
- }
-}
-
static void formatDescription(QDebug &debug, const QString &desc)
{
debug << "description=";
@@ -348,7 +345,7 @@ QDebug operator<<(QDebug debug, const FunctionDocumentation &f)
debug << ", returns " << f.returnType;
if (f.constant)
debug << ", const";
- formatList(debug, ", parameters", f.parameters);
+ formatList(debug, ", parameters", f.parameters, ", ");
debug << ", signature=\"" << f.signature << "\", ";
formatDescription(debug, f.description);
}
@@ -374,16 +371,11 @@ QDebug operator<<(QDebug debug, const ClassDocumentation &c)
QDebugStateSaver saver(debug);
debug.noquote();
debug.nospace();
- debug << "Class(";
- if (c) {
- debug << c.name << ", ";
- formatDescription(debug, c.description);
- formatList(debug, ", enums", c.enums);
- formatList(debug, ", properties", c.properties);
- formatList(debug, ", functions", c.functions);
- } else {
- debug << "invalid";
- }
+ debug << "Class(" << c.name << ", ";
+ formatDescription(debug, c.description);
+ formatList(debug, ", enums", c.enums);
+ formatList(debug, ", properties", c.properties);
+ formatList(debug, ", functions", c.functions);
debug << ')';
return debug;
}
diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.h b/sources/shiboken6/ApiExtractor/classdocumentation.h
index 9c1acbbae..d47101389 100644
--- a/sources/shiboken6/ApiExtractor/classdocumentation.h
+++ b/sources/shiboken6/ApiExtractor/classdocumentation.h
@@ -6,6 +6,8 @@
#include <QtCore/QStringList>
+#include <optional>
+
QT_FORWARD_DECLARE_CLASS(QDebug)
/// An enumeration in a WebXML/doxygen document
@@ -19,6 +21,7 @@ struct EnumDocumentation
struct PropertyDocumentation
{
QString name;
+ QString brief;
QString description;
};
@@ -40,9 +43,14 @@ struct FunctionDocumentation : public FunctionDocumentationQuery
using FunctionDocumentationList = QList<FunctionDocumentation>;
-/// A class/namespace in a WebXML/doxygen document
+/// A WebXML/doxygen document
struct ClassDocumentation
{
+ enum Type {
+ Class, // <class>, class/namespace
+ Header // <header>, grouped global functions/enums
+ };
+
qsizetype indexOfEnum(const QString &name) const;
FunctionDocumentationList findFunctionCandidates(const QString &name,
bool constant) const;
@@ -50,18 +58,17 @@ struct ClassDocumentation
const FunctionDocumentationQuery &q);
qsizetype indexOfProperty(const QString &name) const;
+ Type type = Type::Class;
QString name;
QString description;
QList<EnumDocumentation> enums;
QList<PropertyDocumentation> properties;
FunctionDocumentationList functions;
-
- operator bool() const { return !name.isEmpty(); }
};
/// Parse a WebXML class/namespace document
-ClassDocumentation parseWebXml(const QString &fileName, QString *errorMessage);
+std::optional<ClassDocumentation> parseWebXml(const QString &fileName, QString *errorMessage);
/// Extract the module description from a WebXML module document
QString webXmlModuleDescription(const QString &fileName, QString *errorMessage);
diff --git a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake
index df95fb9d8..4031b4e1a 100644
--- a/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake
+++ b/sources/shiboken6/ApiExtractor/cmake_uninstall.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
diff --git a/sources/shiboken6/ApiExtractor/codesnip.cpp b/sources/shiboken6/ApiExtractor/codesnip.cpp
index 12e71fb70..e2cd5eb35 100644
--- a/sources/shiboken6/ApiExtractor/codesnip.cpp
+++ b/sources/shiboken6/ApiExtractor/codesnip.cpp
@@ -11,11 +11,9 @@
using namespace Qt::StringLiterals;
-static inline QString callOperator() { return QStringLiteral("operator()"); }
-
QString TemplateInstance::expandCode() const
{
- TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name);
+ const auto templateEntry = TypeDatabase::instance()->findTemplate(m_name);
if (!templateEntry) {
const QString m = u"<insert-template> referring to non-existing template '"_s
+ m_name + u"'."_s;
@@ -65,7 +63,7 @@ void CodeSnipAbstract::purgeEmptyFragments()
QRegularExpression CodeSnipAbstract::placeHolderRegex(int index)
{
- return QRegularExpression(u'%' + QString::number(index) + QStringLiteral("\\b"));
+ return QRegularExpression(u'%' + QString::number(index) + "\\b"_L1);
}
void purgeEmptyCodeSnips(QList<CodeSnip> *list)
diff --git a/sources/shiboken6/ApiExtractor/codesnip.h b/sources/shiboken6/ApiExtractor/codesnip.h
index 7a1ab0624..86834a1db 100644
--- a/sources/shiboken6/ApiExtractor/codesnip.h
+++ b/sources/shiboken6/ApiExtractor/codesnip.h
@@ -9,9 +9,10 @@
#include <QtCore/QList>
#include <QtCore/QHash>
-#include <QtCore/QSharedPointer>
#include <QtCore/QString>
+#include <memory>
+
class TemplateInstance
{
public:
@@ -34,7 +35,7 @@ private:
QHash<QString, QString> replaceRules;
};
-using TemplateInstancePtr = QSharedPointer<TemplateInstance>;
+using TemplateInstancePtr = std::shared_ptr<TemplateInstance>;
class CodeSnipFragment
{
@@ -43,7 +44,7 @@ public:
explicit CodeSnipFragment(const QString &code) : m_code(code) {}
explicit CodeSnipFragment(const TemplateInstancePtr &instance) : m_instance(instance) {}
- bool isEmpty() const { return m_code.isEmpty() && m_instance.isNull(); }
+ bool isEmpty() const { return m_code.isEmpty() && !m_instance; }
QString code() const;
@@ -51,7 +52,7 @@ public:
private:
QString m_code;
- QSharedPointer<TemplateInstance> m_instance;
+ std::shared_ptr<TemplateInstance> m_instance;
};
class CodeSnipAbstract : public CodeSnipHelpers
diff --git a/sources/shiboken6/ApiExtractor/complextypeentry.h b/sources/shiboken6/ApiExtractor/complextypeentry.h
index fd17fe572..5b884f2cc 100644
--- a/sources/shiboken6/ApiExtractor/complextypeentry.h
+++ b/sources/shiboken6/ApiExtractor/complextypeentry.h
@@ -4,7 +4,9 @@
#ifndef COMPLEXTYPEENTRY_H
#define COMPLEXTYPEENTRY_H
-#include "typesystem.h"
+#include "configurabletypeentry.h"
+#include "typesystem_enums.h"
+#include "modifications_typedefs.h"
#include "pymethoddefentry.h"
#include <QtCore/QSet>
@@ -26,11 +28,12 @@ struct TypeSystemProperty
QString write;
QString reset;
QString designable;
+ QString notify; // Q_PROPERTY/C++ only
// Indicates whether actual code is generated instead of relying on libpyside.
bool generateGetSetDef = false;
};
-class ComplexTypeEntry : public TypeEntry
+class ComplexTypeEntry : public ConfigurableTypeEntry
{
public:
enum TypeFlag {
@@ -39,7 +42,9 @@ public:
ForceAbstract = 0x8,
// Indicates that the instances are used to create hierarchies
// like widgets; parent ownership heuristics are enabled for them.
- ParentManagement = 0x10
+ ParentManagement = 0x10,
+ DisableQtMetaObjectFunctions = 0x20,
+ Typedef = 0x40 // Result of a <typedef-type>
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@@ -50,7 +55,7 @@ public:
};
explicit ComplexTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
bool isComplex() const override;
@@ -67,7 +72,22 @@ public:
FunctionModificationList functionModifications() const;
void setFunctionModifications(const FunctionModificationList &functionModifications);
void addFunctionModification(const FunctionModification &functionModification);
- FunctionModificationList functionModifications(const QString &signature) const;
+ FunctionModificationList functionModifications(const QStringList &signatures) const;
+
+ const CodeSnipList &codeSnips() const;
+ CodeSnipList &codeSnips();
+ void setCodeSnips(const CodeSnipList &codeSnips);
+ void addCodeSnip(const CodeSnip &codeSnip);
+
+ void setDocModification(const DocModificationList& docMods);
+ /// Class documentation modifications
+ DocModificationList docModifications() const;
+ /// Function documentation modifications (matching signature)
+ DocModificationList functionDocModifications() const;
+
+ /// Extra includes for function arguments determined by the meta builder.
+ const IncludeList &argumentIncludes() const;
+ void addArgumentInclude(const Include &newInclude);
AddedFunctionList addedFunctions() const;
void setAddedFunctions(const AddedFunctionList &addedFunctions);
@@ -118,9 +138,9 @@ public:
QString hashFunction() const;
void setHashFunction(const QString &hashFunction);
- void setBaseContainerType(const ComplexTypeEntry *baseContainer);
+ void setBaseContainerType(const ComplexTypeEntryCPtr &baseContainer);
- const ComplexTypeEntry *baseContainerType() const;
+ ComplexTypeEntryCPtr baseContainerType() const;
TypeSystem::ExceptionHandling exceptionHandling() const;
void setExceptionHandling(TypeSystem::ExceptionHandling e);
@@ -134,7 +154,7 @@ public:
TypeEntry *clone() const override;
- void useAsTypedef(const ComplexTypeEntry *source);
+ void useAsTypedef(const ComplexTypeEntryCPtr &source);
TypeSystem::SnakeCase snakeCase() const;
void setSnakeCase(TypeSystem::SnakeCase sc);
diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp
index c8ec9b563..b6eda651c 100644
--- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp
+++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.cpp
@@ -6,6 +6,8 @@
#include <QtCore/QDebug>
#include <QtCore/QHash>
+using namespace Qt::StringLiterals;
+
// ProxyEntityResolver proxies a QXmlStreamEntityResolver set by the user
// on ConditionalStreamReader and stores entity definitions from the
// <?entity name value?> processing instruction in a cache
@@ -126,7 +128,7 @@ bool ConditionalStreamReader::readEntityDefinitonPi()
const auto data = m_reader.processingInstructionData();
const auto separator = data.indexOf(u' ');
if (separator <= 0 || separator == data.size() - 1) {
- m_reader.raiseError(u"Malformed entity definition: "_qs + data.toString());
+ m_reader.raiseError(u"Malformed entity definition: "_s + data.toString());
return false;
}
defineEntity(data.left(separator).toString(),
@@ -163,15 +165,15 @@ QStringList ConditionalStreamReader::platformConditions()
{
QStringList result;
#if defined (Q_OS_UNIX)
- result << QStringLiteral("unix");
+ result << "unix"_L1;
#endif
#if defined (Q_OS_LINUX)
- result << QStringLiteral("linux");
+ result << "linux"_L1;
#elif defined (Q_OS_MACOS)
- result << QStringLiteral("darwin");
+ result << "darwin"_L1;
#elif defined (Q_OS_WINDOWS)
- result << QStringLiteral("windows");
+ result << "windows"_L1;
#endif
return result;
}
diff --git a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h
index a273fd0ca..730697525 100644
--- a/sources/shiboken6/ApiExtractor/conditionalstreamreader.h
+++ b/sources/shiboken6/ApiExtractor/conditionalstreamreader.h
@@ -26,6 +26,8 @@ class ProxyEntityResolver;
class ConditionalStreamReader
{
public:
+ Q_DISABLE_COPY_MOVE(ConditionalStreamReader)
+
using TokenType = QXmlStreamReader::TokenType;
explicit ConditionalStreamReader(QIODevice *iod);
explicit ConditionalStreamReader(const QString &s);
diff --git a/sources/shiboken6/ApiExtractor/configurabletypeentry.h b/sources/shiboken6/ApiExtractor/configurabletypeentry.h
new file mode 100644
index 000000000..59522e16c
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/configurabletypeentry.h
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CONFIGURABLETYPEENTRY_H
+#define CONFIGURABLETYPEENTRY_H
+
+#include "typesystem.h"
+
+class ConfigurableTypeEntryPrivate;
+
+class ConfigurableTypeEntry : public TypeEntry
+{
+public:
+ explicit ConfigurableTypeEntry(const QString &entryName, Type t,
+ const QVersionNumber &vr,
+ const TypeEntryCPtr &parent);
+
+ TypeEntry *clone() const override;
+
+ QString configCondition() const;
+ void setConfigCondition(const QString &c);
+ bool hasConfigCondition() const;
+
+protected:
+ explicit ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d);
+};
+
+#endif // CONFIGURABLETYPEENTRY_H
diff --git a/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h b/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h
index d88c2b07f..a16a7ad12 100644
--- a/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h
+++ b/sources/shiboken6/ApiExtractor/constantvaluetypeentry.h
@@ -12,7 +12,7 @@ class ConstantValueTypeEntry : public TypeEntry
{
public:
explicit ConstantValueTypeEntry(const QString& name,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/containertypeentry.h b/sources/shiboken6/ApiExtractor/containertypeentry.h
index 34ee08808..b2003816b 100644
--- a/sources/shiboken6/ApiExtractor/containertypeentry.h
+++ b/sources/shiboken6/ApiExtractor/containertypeentry.h
@@ -5,18 +5,23 @@
#define CONTAINERTYPEENTRY_H
#include "complextypeentry.h"
+#include "customconversion_typedefs.h"
class ContainerTypeEntryPrivate;
+struct OpaqueContainer // Generate an opaque container for an instantiation under name
+{
+ QStringList instantiations;
+ QString name;
+
+ QString templateParameters() const;
+};
+
+using OpaqueContainers = QList<OpaqueContainer>;
+
class ContainerTypeEntry : public ComplexTypeEntry
{
public:
- struct OpaqueContainer // Generate an opaque container for an instantiation under name
- {
- QString instantiation;
- QString name;
- };
- using OpaqueContainers = QList<OpaqueContainer>;
enum ContainerKind {
ListContainer,
@@ -24,17 +29,25 @@ public:
MapContainer,
MultiMapContainer,
PairContainer,
+ SpanContainer, // Fixed size
};
explicit ContainerTypeEntry(const QString &entryName, ContainerKind containerKind,
- const QVersionNumber &vr, const TypeEntry *parent);
+ const QVersionNumber &vr, const TypeEntryCPtr &parent);
ContainerKind containerKind() const;
+ /// Number of template parameters (except allocators)
+ qsizetype templateParameterCount() const;
+
const OpaqueContainers &opaqueContainers() const;
- void addOpaqueContainer(OpaqueContainer r);
- bool generateOpaqueContainer(const QString &instantiation) const;
- QString opaqueContainerName(const QString &instantiation) const;
+ void appendOpaqueContainers(const OpaqueContainers &l);
+ bool generateOpaqueContainer(const QStringList &instantiations) const;
+ QString opaqueContainerName(const QStringList &instantiations) const;
+
+ bool hasCustomConversion() const;
+ void setCustomConversion(const CustomConversionPtr &customConversion);
+ CustomConversionPtr customConversion() const;
TypeEntry *clone() const override;
@@ -45,4 +58,6 @@ protected:
explicit ContainerTypeEntry(ContainerTypeEntryPrivate *d);
};
+QDebug operator<<(QDebug d, const OpaqueContainer &oc);
+
#endif // CONTAINERTYPEENTRY_H
diff --git a/sources/shiboken6/ApiExtractor/customconversion.cpp b/sources/shiboken6/ApiExtractor/customconversion.cpp
new file mode 100644
index 000000000..4cfd1b974
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/customconversion.cpp
@@ -0,0 +1,197 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "customconversion.h"
+#include "containertypeentry.h"
+#include "customtypenentry.h"
+#include "primitivetypeentry.h"
+#include "valuetypeentry.h"
+
+#include <QtCore/qdebug.h>
+
+using namespace Qt::StringLiterals;
+
+CustomConversion::CustomConversion(const TypeEntryCPtr &ownerType) :
+ m_ownerType(ownerType)
+{
+}
+
+TypeEntryCPtr CustomConversion::ownerType() const
+{
+ return m_ownerType;
+}
+
+QString CustomConversion::nativeToTargetConversion() const
+{
+ return m_nativeToTargetConversion;
+}
+
+void CustomConversion::setNativeToTargetConversion(const QString &nativeToTargetConversion)
+{
+ m_nativeToTargetConversion = nativeToTargetConversion;
+}
+
+bool CustomConversion::replaceOriginalTargetToNativeConversions() const
+{
+ return m_replaceOriginalTargetToNativeConversions;
+}
+
+void CustomConversion::setReplaceOriginalTargetToNativeConversions(bool r)
+{
+ m_replaceOriginalTargetToNativeConversions = r;
+}
+
+bool CustomConversion::hasTargetToNativeConversions() const
+{
+ return !(m_targetToNativeConversions.isEmpty());
+}
+
+TargetToNativeConversions &CustomConversion::targetToNativeConversions()
+{
+ return m_targetToNativeConversions;
+}
+
+const TargetToNativeConversions &CustomConversion::targetToNativeConversions() const
+{
+ return m_targetToNativeConversions;
+}
+
+void CustomConversion::addTargetToNativeConversion(const QString &sourceTypeName,
+ const QString &sourceTypeCheck,
+ const QString &conversion)
+{
+ m_targetToNativeConversions.append(TargetToNativeConversion(sourceTypeName,
+ sourceTypeCheck,
+ conversion));
+}
+
+TargetToNativeConversion::TargetToNativeConversion(const QString &sourceTypeName,
+ const QString &sourceTypeCheck,
+ const QString &conversion) :
+ m_sourceTypeName(sourceTypeName), m_sourceTypeCheck(sourceTypeCheck),
+ m_conversion(conversion)
+{
+}
+
+TypeEntryCPtr TargetToNativeConversion::sourceType() const
+{
+ return m_sourceType;
+}
+
+void TargetToNativeConversion::setSourceType(const TypeEntryCPtr &sourceType)
+{
+ m_sourceType = sourceType;
+}
+
+bool TargetToNativeConversion::isCustomType() const
+{
+ return m_sourceType == nullptr;
+}
+
+QString TargetToNativeConversion::sourceTypeName() const
+{
+ return m_sourceTypeName;
+}
+
+QString TargetToNativeConversion::sourceTypeCheck() const
+{
+ if (!m_sourceTypeCheck.isEmpty())
+ return m_sourceTypeCheck;
+
+ if (m_sourceType != nullptr && m_sourceType->isCustom()) {
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(m_sourceType);
+ if (cte->hasCheckFunction()) {
+ QString result = cte->checkFunction();
+ if (result != u"true") // For PyObject, which is always true
+ result += u"(%in)"_s;
+ return result;
+ }
+ }
+
+ return {};
+}
+
+QString TargetToNativeConversion::conversion() const
+{
+ return m_conversion;
+}
+
+void TargetToNativeConversion::setConversion(const QString &conversion)
+{
+ m_conversion = conversion;
+}
+
+void TargetToNativeConversion::formatDebug(QDebug &debug) const
+{
+ debug << "(source=\"" << m_sourceTypeName << '"';
+ if (debug.verbosity() > 2)
+ debug << ", conversion=\"" << m_conversion << '"';
+ if (isCustomType())
+ debug << ", [custom]";
+ debug << ')';
+}
+
+CustomConversionPtr CustomConversion::getCustomConversion(const TypeEntryCPtr &type)
+{
+ if (type->isPrimitive())
+ return std::static_pointer_cast<const PrimitiveTypeEntry>(type)->customConversion();
+ if (type->isContainer())
+ return std::static_pointer_cast<const ContainerTypeEntry>(type)->customConversion();
+ if (type->isValue())
+ return std::static_pointer_cast<const ValueTypeEntry>(type)->customConversion();
+ return {};
+}
+
+void CustomConversion::formatDebug(QDebug &debug) const
+{
+ debug << "(owner=\"" << m_ownerType->qualifiedCppName() << '"';
+ if (!m_nativeToTargetConversion.isEmpty())
+ debug << ", nativeToTargetConversion=\"" << m_nativeToTargetConversion << '"';
+ if (!m_targetToNativeConversions.isEmpty()) {
+ debug << ", targetToNativeConversions=[";
+ for (qsizetype i = 0, size = m_targetToNativeConversions.size(); i < size; ++i) {
+ if (i)
+ debug << ", ";
+ debug << m_targetToNativeConversions.at(i);
+
+ }
+ debug << ']';
+ }
+ if (m_replaceOriginalTargetToNativeConversions)
+ debug << ", [replaceOriginalTargetToNativeConversions]";
+ debug << ')';
+}
+
+QDebug operator<<(QDebug debug, const TargetToNativeConversion &t)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "TargetToNativeConversion";
+ t.formatDebug(debug);
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const CustomConversion &c)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "CustomConversion";
+ c.formatDebug(debug);
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const CustomConversionPtr &cptr)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "CustomConversionPtr";
+ if (auto *c = cptr.get()) {
+ c->formatDebug(debug);
+ } else {
+ debug << "(0)";
+ }
+ return debug;
+}
diff --git a/sources/shiboken6/ApiExtractor/customconversion.h b/sources/shiboken6/ApiExtractor/customconversion.h
index 172600d48..fd0a67759 100644
--- a/sources/shiboken6/ApiExtractor/customconversion.h
+++ b/sources/shiboken6/ApiExtractor/customconversion.h
@@ -4,61 +4,78 @@
#ifndef CUSTOMCONVERSION_H
#define CUSTOMCONVERSION_H
-#include "typesystem_enums.h"
+#include "customconversion_typedefs.h"
+#include "typesystem_typedefs.h"
#include <QtCore/QList>
#include <QtCore/QString>
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
class TypeEntry;
+class TargetToNativeConversion
+{
+public:
+ explicit TargetToNativeConversion(const QString &sourceTypeName,
+ const QString &sourceTypeCheck,
+ const QString &conversion = {});
+
+ TypeEntryCPtr sourceType() const;
+ void setSourceType(const TypeEntryCPtr &sourceType);
+ bool isCustomType() const;
+ QString sourceTypeName() const;
+ QString sourceTypeCheck() const;
+ QString conversion() const;
+ void setConversion(const QString &conversion);
+
+ void formatDebug(QDebug &d) const;
+
+private:
+ TypeEntryCPtr m_sourceType;
+ QString m_sourceTypeName;
+ QString m_sourceTypeCheck;
+ QString m_conversion;
+};
+
+using TargetToNativeConversions = QList<TargetToNativeConversion>;
+
class CustomConversion
{
public:
- CustomConversion(TypeEntry* ownerType);
- ~CustomConversion();
+ explicit CustomConversion(const TypeEntryCPtr &ownerType);
- const TypeEntry* ownerType() const;
+ TypeEntryCPtr ownerType() const;
QString nativeToTargetConversion() const;
- void setNativeToTargetConversion(const QString& nativeToTargetConversion);
-
- class TargetToNativeConversion
- {
- public:
- TargetToNativeConversion(const QString& sourceTypeName,
- const QString& sourceTypeCheck,
- const QString& conversion = QString());
- ~TargetToNativeConversion();
-
- const TypeEntry* sourceType() const;
- void setSourceType(const TypeEntry* sourceType);
- bool isCustomType() const;
- QString sourceTypeName() const;
- QString sourceTypeCheck() const;
- QString conversion() const;
- void setConversion(const QString& conversion);
- private:
- struct TargetToNativeConversionPrivate;
- TargetToNativeConversionPrivate* m_d;
- };
-
- /**
- * Returns true if the target to C++ custom conversions should
- * replace the original existing ones, and false if the custom
- * conversions should be added to the original.
- */
+ void setNativeToTargetConversion(const QString &nativeToTargetConversion);
+
+ /// Returns true if the target to C++ custom conversions should
+ /// replace the original existing ones, and false if the custom
+ /// conversions should be added to the original.
bool replaceOriginalTargetToNativeConversions() const;
- void setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions);
+ void setReplaceOriginalTargetToNativeConversions(bool r);
- using TargetToNativeConversions = QList<TargetToNativeConversion *>;
bool hasTargetToNativeConversions() const;
- TargetToNativeConversions& targetToNativeConversions();
- const TargetToNativeConversions& targetToNativeConversions() const;
- void addTargetToNativeConversion(const QString& sourceTypeName,
- const QString& sourceTypeCheck,
- const QString& conversion = QString());
+ TargetToNativeConversions &targetToNativeConversions();
+ const TargetToNativeConversions &targetToNativeConversions() const;
+ void addTargetToNativeConversion(const QString &sourceTypeName,
+ const QString &sourceTypeCheck,
+ const QString &conversion = QString());
+
+ /// Return the custom conversion of a type; helper for type system parser
+ static CustomConversionPtr getCustomConversion(const TypeEntryCPtr &type);
+
+ void formatDebug(QDebug &debug) const;
+
private:
- struct CustomConversionPrivate;
- CustomConversionPrivate* m_d;
+ TypeEntryCPtr m_ownerType;
+ QString m_nativeToTargetConversion;
+ TargetToNativeConversions m_targetToNativeConversions;
+ bool m_replaceOriginalTargetToNativeConversions = false;
};
+QDebug operator<<(QDebug debug, const TargetToNativeConversion &t);
+QDebug operator<<(QDebug debug, const CustomConversion &c);
+QDebug operator<<(QDebug debug, const CustomConversionPtr &cptr);
+
#endif // CUSTOMCONVERSION_H
diff --git a/sources/shiboken6/ApiExtractor/customconversion_typedefs.h b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h
new file mode 100644
index 000000000..6528f7d7b
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/customconversion_typedefs.h
@@ -0,0 +1,14 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CUSTOMCONVERSION_TYPEDEFS_H
+#define CUSTOMCONVERSION_TYPEDEFS_H
+
+#include <QtCore/QList>
+
+#include <memory>
+
+class CustomConversion;
+using CustomConversionPtr = std::shared_ptr<CustomConversion>;
+
+#endif // CUSTOMCONVERSION_TYPEDEFS_H
diff --git a/sources/shiboken6/ApiExtractor/customtypenentry.h b/sources/shiboken6/ApiExtractor/customtypenentry.h
index e0dda4387..a57bb858f 100644
--- a/sources/shiboken6/ApiExtractor/customtypenentry.h
+++ b/sources/shiboken6/ApiExtractor/customtypenentry.h
@@ -10,7 +10,7 @@ class CustomTypeEntry : public TypeEntry
{
public:
explicit CustomTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/debughelpers_p.h b/sources/shiboken6/ApiExtractor/debughelpers_p.h
new file mode 100644
index 000000000..81ebbb3b9
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/debughelpers_p.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef DEBUGHELPERS_P_H
+#define DEBUGHELPERS_P_H
+
+#include <QtCore/QDebug>
+#include <memory>
+
+template <class T>
+inline QDebug operator<<(QDebug debug, const std::shared_ptr<T> &ptr)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "std::shared_ptr(" << ptr.get() << ")";
+ return debug;
+}
+
+template <class It>
+inline void formatSequence(QDebug &d, It i1, It i2,
+ const char *separator=", ")
+{
+ for (It i = i1; i != i2; ++i) {
+ if (i != i1)
+ d << separator;
+ d << *i;
+ }
+}
+
+template <class It>
+inline static void formatPtrSequence(QDebug &d, It i1, It i2,
+ const char *separator=", ")
+{
+ for (It i = i1; i != i2; ++i) {
+ if (i != i1)
+ d << separator;
+ d << i->get();
+ }
+}
+
+template <class Container>
+static void formatList(QDebug &d, const char *name, const Container &c,
+ const char *separator=", ")
+{
+ if (const auto size = c.size()) {
+ d << ", " << name << '[' << size << "]=(";
+ for (qsizetype i = 0; i < size; ++i) {
+ if (i)
+ d << separator;
+ d << c.at(i);
+ }
+ d << ')';
+ }
+}
+
+#endif // DEBUGHELPERS_P_H
diff --git a/sources/shiboken6/ApiExtractor/dependency.h b/sources/shiboken6/ApiExtractor/dependency.h
index f0e525e26..aa280de03 100644
--- a/sources/shiboken6/ApiExtractor/dependency.h
+++ b/sources/shiboken6/ApiExtractor/dependency.h
@@ -13,8 +13,8 @@
class AbstractMetaClass;
struct Dependency {
- AbstractMetaClass *parent;
- AbstractMetaClass *child;
+ AbstractMetaClassPtr parent;
+ AbstractMetaClassPtr child;
};
using Dependencies = QList<Dependency>;
diff --git a/sources/shiboken6/ApiExtractor/docparser.cpp b/sources/shiboken6/ApiExtractor/docparser.cpp
index ea3828a43..468fe1098 100644
--- a/sources/shiboken6/ApiExtractor/docparser.cpp
+++ b/sources/shiboken6/ApiExtractor/docparser.cpp
@@ -1,15 +1,17 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
#include "docparser.h"
-#include "classdocumentation.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
-#include "abstractmetafield.h"
#include "abstractmetafunction.h"
#include "abstractmetalang.h"
+#include "abstractmetatype.h"
#include "messages.h"
#include "modifications.h"
#include "reporthandler.h"
-#include "typesystem.h"
+#include "enumtypeentry.h"
+#include "complextypeentry.h"
#include "xmlutils.h"
#include <QtCore/QBuffer>
@@ -29,15 +31,37 @@
using namespace Qt::StringLiterals;
-DocParser::DocParser()
+static inline bool isXpathDocModification(const DocModification &mod)
{
-#ifdef HAVE_LIBXSLT
- xmlSubstituteEntitiesDefault(1);
-#endif
+ return mod.mode() == TypeSystem::DocModificationXPathReplace;
+}
+
+static inline bool isNotXpathDocModification(const DocModification &mod)
+{
+ return mod.mode() != TypeSystem::DocModificationXPathReplace;
+}
+
+static void removeXpathDocModifications(DocModificationList *l)
+{
+ l->erase(std::remove_if(l->begin(), l->end(), isXpathDocModification), l->end());
+}
+
+static void removeNonXpathDocModifications(DocModificationList *l)
+{
+ l->erase(std::remove_if(l->begin(), l->end(), isNotXpathDocModification), l->end());
}
+DocParser::DocParser() = default;
DocParser::~DocParser() = default;
+void DocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &)
+{
+}
+
+void DocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &)
+{
+}
+
QString DocParser::getDocumentation(const XQueryPtr &xquery, const QString& query,
const DocModificationList& mods)
{
@@ -84,22 +108,90 @@ bool DocParser::skipForQuery(const AbstractMetaFunctionCPtr &func)
usesRValueReference);
}
-AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClass *metaClass)
+DocModificationList DocParser::getDocModifications(const AbstractMetaClassCPtr &cppClass)
+
+{
+ auto result = cppClass->typeEntry()->docModifications();
+ removeXpathDocModifications(&result);
+ return result;
+}
+
+static void filterBySignature(const AbstractMetaFunctionCPtr &func, DocModificationList *l)
{
- auto result = metaClass->functionsInTargetLang();
- for (int i = result.size() - 1; i >= 0; --i) {
- if (DocParser::skipForQuery(result.at(i)) || result.at(i)->isUserAdded())
- result.removeAt(i);
+ if (!l->isEmpty()) {
+ const QString minimalSignature = func->minimalSignature();
+ const auto filter = [&minimalSignature](const DocModification &mod) {
+ return mod.signature() != minimalSignature;
+ };
+ l->erase(std::remove_if(l->begin(), l->end(), filter), l->end());
+ }
+}
+
+DocModificationList DocParser::getDocModifications(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass)
+{
+ DocModificationList result;
+ if (func->isUserAdded()) {
+ result = func->addedFunctionDocModifications();
+ removeXpathDocModifications(&result);
+ } else if (cppClass != nullptr) {
+ result = cppClass->typeEntry()->functionDocModifications();
+ removeXpathDocModifications(&result);
+ filterBySignature(func, &result);
}
return result;
}
-static inline bool isXpathDocModification(const DocModification &mod)
+DocModificationList DocParser::getXpathDocModifications(const AbstractMetaClassCPtr &cppClass)
{
- return mod.mode() == TypeSystem::DocModificationXPathReplace;
+ auto result = cppClass->typeEntry()->docModifications();
+ removeNonXpathDocModifications(&result);
+ return result;
}
-QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml)
+DocModificationList DocParser::getXpathDocModifications(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass)
+{
+ DocModificationList result;
+ if (func->isUserAdded()) {
+ result = func->addedFunctionDocModifications();
+ removeNonXpathDocModifications(&result);
+ } else if (cppClass != nullptr) {
+ result = cppClass->typeEntry()->functionDocModifications();
+ removeNonXpathDocModifications(&result);
+ filterBySignature(func, &result);
+ }
+ return result;
+}
+
+QString DocParser::enumBaseClass(const AbstractMetaEnum &e)
+{
+ switch (e.typeEntry()->pythonEnumType()) {
+ case TypeSystem::PythonEnumType::IntEnum:
+ return u"IntEnum"_s;
+ case TypeSystem::PythonEnumType::Flag:
+ return u"Flag"_s;
+ case TypeSystem::PythonEnumType::IntFlag:
+ return u"IntFlag"_s;
+ default:
+ break;
+ }
+ return e.typeEntry()->flags() != nullptr ? u"Flag"_s : u"Enum"_s;
+}
+
+AbstractMetaFunctionCList DocParser::documentableFunctions(const AbstractMetaClassCPtr &metaClass)
+{
+ auto result = metaClass->functionsInTargetLang();
+ for (auto i = result.size() - 1; i >= 0; --i) {
+ if (DocParser::skipForQuery(result.at(i)) || result.at(i)->isUserAdded())
+ result.removeAt(i);
+ }
+ result.append(metaClass->cppSignalFunctions());
+ return result;
+}
+
+QString DocParser::applyDocModifications(const DocModificationList& xpathMods,
+ const QString& xml)
{
const char xslPrefix[] =
R"(<xsl:template match="/">
@@ -113,32 +205,28 @@ R"(<xsl:template match="/">
</xsl:template>
)";
- if (mods.isEmpty() || xml.isEmpty()
- || !std::any_of(mods.cbegin(), mods.cend(), isXpathDocModification)) {
+ if (xpathMods.isEmpty() || xml.isEmpty())
return xml;
- }
QString xsl = QLatin1StringView(xslPrefix);
- for (const DocModification &mod : mods) {
- if (isXpathDocModification(mod)) {
- QString xpath = mod.xpath();
- xpath.replace(u'"', u"&quot;"_s);
- xsl += u"<xsl:template match=\""_s
- + xpath + u"\">"_s
- + mod.code() + u"</xsl:template>\n"_s;
- }
+ for (const DocModification &mod : xpathMods) {
+ Q_ASSERT(isXpathDocModification(mod));
+ QString xpath = mod.xpath();
+ xpath.replace(u'"', u"&quot;"_s);
+ xsl += "<xsl:template match=\""_L1 + xpath + "\">"_L1
+ + mod.code() + "</xsl:template>\n"_L1;
}
QString errorMessage;
const QString result = xsl_transform(xml, xsl, &errorMessage);
if (!errorMessage.isEmpty())
qCWarning(lcShibokenDoc, "%s",
- qPrintable(msgXpathDocModificationError(mods, errorMessage)));
+ qPrintable(msgXpathDocModificationError(xpathMods, errorMessage)));
if (result == xml) {
const QString message = u"Query did not result in any modifications to \""_s
+ xml + u'"';
qCWarning(lcShibokenDoc, "%s",
- qPrintable(msgXpathDocModificationError(mods, message)));
+ qPrintable(msgXpathDocModificationError(xpathMods, message)));
}
return result;
}
diff --git a/sources/shiboken6/ApiExtractor/docparser.h b/sources/shiboken6/ApiExtractor/docparser.h
index bf305272a..6d458b25a 100644
--- a/sources/shiboken6/ApiExtractor/docparser.h
+++ b/sources/shiboken6/ApiExtractor/docparser.h
@@ -3,11 +3,12 @@
#ifndef DOCPARSER_H
#define DOCPARSER_H
-#include "typesystem_typedefs.h"
#include "abstractmetalang_typedefs.h"
+#include "modifications_typedefs.h"
#include <QtCore/QString>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
class AbstractMetaClass;
class DocModification;
@@ -20,13 +21,15 @@ struct FunctionDocumentation;
class DocParser
{
public:
- Q_DISABLE_COPY(DocParser)
+ Q_DISABLE_COPY_MOVE(DocParser)
- using XQueryPtr = QSharedPointer<XQuery>;
+ using XQueryPtr = std::shared_ptr<XQuery>;
DocParser();
virtual ~DocParser();
- virtual void fillDocumentation(AbstractMetaClass* metaClass) = 0;
+ virtual void fillDocumentation(const AbstractMetaClassPtr &metaClass) = 0;
+ virtual void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f);
+ virtual void fillGlobalEnumDocumentation(AbstractMetaEnum &e);
/**
* Process and retrieves documentation concerning the entire
@@ -91,14 +94,25 @@ public:
static bool skipForQuery(const AbstractMetaFunctionCPtr &func);
+ /// Helper to return the documentation modifications for a class
+ /// or a member function.
+ static DocModificationList getDocModifications(const AbstractMetaClassCPtr &cppClass);
+ static DocModificationList getDocModifications(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass = {});
+ static DocModificationList getXpathDocModifications(const AbstractMetaClassCPtr &cppClass);
+ static DocModificationList getXpathDocModifications(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass = {});
+
+ static QString enumBaseClass(const AbstractMetaEnum &e);
+
protected:
static QString getDocumentation(const XQueryPtr &xquery,
const QString &query,
const DocModificationList &mods);
- static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClass *metaClass);
+ static AbstractMetaFunctionCList documentableFunctions(const AbstractMetaClassCPtr &metaClass);
- static QString applyDocModifications(const DocModificationList &mods, const QString &xml);
+ static QString applyDocModifications(const DocModificationList &xpathMods, const QString &xml);
private:
QString m_packageName;
diff --git a/sources/shiboken6/ApiExtractor/documentation.cpp b/sources/shiboken6/ApiExtractor/documentation.cpp
index 6c4d7166e..33cf0e9fb 100644
--- a/sources/shiboken6/ApiExtractor/documentation.cpp
+++ b/sources/shiboken6/ApiExtractor/documentation.cpp
@@ -35,12 +35,6 @@ void Documentation::setFormat(Documentation::Format f)
m_format = f;
}
-bool Documentation::equals(const Documentation &rhs) const
-{
- return m_format == rhs.m_format && m_detailed == rhs.m_detailed
- && m_brief == rhs.m_brief;
-}
-
void Documentation::setDetailed(const QString &detailed)
{
m_detailed = detailed.trimmed();
diff --git a/sources/shiboken6/ApiExtractor/documentation.h b/sources/shiboken6/ApiExtractor/documentation.h
index a18bb1a13..df9d5d614 100644
--- a/sources/shiboken6/ApiExtractor/documentation.h
+++ b/sources/shiboken6/ApiExtractor/documentation.h
@@ -5,6 +5,7 @@
#define DOCUMENTATION_H
#include <QtCore/QString>
+#include <QtCore/QtCompare>
QT_FORWARD_DECLARE_CLASS(QDebug)
@@ -44,16 +45,19 @@ public:
void setBrief(const QString &brief);
private:
+ friend bool comparesEqual(const Documentation &lhs,
+ const Documentation &rhs) noexcept
+ {
+ return lhs.m_format == rhs.m_format && lhs.m_detailed == rhs.m_detailed
+ && lhs.m_brief == rhs.m_brief;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(Documentation)
+
QString m_detailed;
QString m_brief;
Format m_format = Documentation::Native;
};
-inline bool operator==(const Documentation &d1, const Documentation &d2)
-{ return d1.equals(d2); }
-inline bool operator!=(const Documentation &d1, const Documentation &d2)
-{ return !d1.equals(d2); }
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const Documentation &);
#endif
diff --git a/sources/shiboken6/ApiExtractor/dotview.cpp b/sources/shiboken6/ApiExtractor/dotview.cpp
index 4fd795a84..0bd192257 100644
--- a/sources/shiboken6/ApiExtractor/dotview.cpp
+++ b/sources/shiboken6/ApiExtractor/dotview.cpp
@@ -9,12 +9,14 @@
#include <QtCore/QProcess>
#include <QtCore/QTemporaryFile>
+using namespace Qt::StringLiterals;
+
bool showDotGraph(const QString &name, const QString &graph)
{
- const QString imageType = u"jpg"_qs;
+ constexpr auto imageType = "jpg"_L1;
// Write out the graph to a temporary file
- QTemporaryFile dotFile(QDir::tempPath() + u'/' + name + u"_XXXXXX.dot"_qs);
+ QTemporaryFile dotFile(QDir::tempPath() + u'/' + name + u"_XXXXXX.dot"_s);
if (!dotFile.open()) {
qWarning("Cannot open temporary file: %s", qPrintable(dotFile.errorString()));
return false;
@@ -26,7 +28,7 @@ bool showDotGraph(const QString &name, const QString &graph)
// Convert to image using "dot"
const QString imageFile = tempDotFile.left(tempDotFile.size() - 3) + imageType;
QProcess process;
- process.start(u"dot"_qs, {u"-T"_qs + imageType, u"-o"_qs + imageFile, tempDotFile});
+ process.start(u"dot"_s, {u"-T"_s + imageType, u"-o"_s + imageFile, tempDotFile});
if (!process.waitForStarted() || !process.waitForFinished()) {
qWarning("Image conversion failed: %s", qPrintable(process.errorString()));
return false;
@@ -41,9 +43,9 @@ bool showDotGraph(const QString &name, const QString &graph)
// Launch image. Should use QDesktopServices::openUrl(),
// but we don't link against QtGui
#ifdef Q_OS_UNIX
- const QString imageViewer = u"gwenview"_qs;
+ constexpr auto imageViewer = "gwenview"_L1;
#else
- const QString imageViewer = u"mspaint"_qs;
+ constexpr auto imageViewer = "mspaint"_L1;
#endif
if (!QProcess::startDetached(imageViewer, {imageFile})) {
qWarning("Failed to launch viewer: %s", qPrintable(imageViewer));
diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.cpp b/sources/shiboken6/ApiExtractor/doxygenparser.cpp
index b8d97a748..da790015f 100644
--- a/sources/shiboken6/ApiExtractor/doxygenparser.cpp
+++ b/sources/shiboken6/ApiExtractor/doxygenparser.cpp
@@ -2,10 +2,12 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "doxygenparser.h"
+#include "abstractmetaargument.h"
#include "abstractmetalang.h"
#include "abstractmetafield.h"
#include "abstractmetafunction.h"
#include "abstractmetaenum.h"
+#include "abstractmetatype.h"
#include "documentation.h"
#include "messages.h"
#include "modifications.h"
@@ -39,7 +41,7 @@ Documentation DoxygenParser::retrieveModuleDocumentation()
return retrieveModuleDocumentation(packageName());
}
-void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
+void DoxygenParser::fillDocumentation(const AbstractMetaClassPtr &metaClass)
{
if (!metaClass)
return;
@@ -52,13 +54,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
doxyFileSuffix += metaClass->name();
doxyFileSuffix += u".xml"_s;
- const char* prefixes[] = { "class", "struct", "namespace" };
+ static constexpr QLatin1StringView prefixes[] = { "class"_L1, "struct"_L1, "namespace"_L1 };
bool isProperty = false;
QString doxyFilePath;
- for (const char *prefix : prefixes) {
- doxyFilePath = documentationDataDirectory() + u'/'
- + QLatin1StringView(prefix) + doxyFileSuffix;
+ for (const auto &prefix : prefixes) {
+ doxyFilePath = documentationDataDirectory() + u'/' + prefix + doxyFileSuffix;
if (QFile::exists(doxyFilePath))
break;
doxyFilePath.clear();
@@ -74,12 +75,12 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
QString errorMessage;
XQueryPtr xquery = XQuery::create(doxyFilePath, &errorMessage);
- if (xquery.isNull()) {
+ if (!xquery) {
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
return;
}
- static const QList<QPair<Documentation::Type, QString>> docTags = {
+ static const QList<std::pair<Documentation::Type, QString>> docTags = {
{ Documentation::Brief, u"briefdescription"_s },
{ Documentation::Detailed, u"detaileddescription"_s }
};
@@ -117,7 +118,7 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
+ func->originalName() + u"\"]"_s;
if (func->arguments().isEmpty()) {
- QString args = func->isConstant() ? u"() const "_s : u"()"_s;
+ QString args = func->isConstant() ? u"() const"_s : u"()"_s;
query += u"/../argsstring[text()=\""_s + args + u"\"]"_s;
} else {
int i = 1;
@@ -148,16 +149,17 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
funcQuery += u"/../"_s + tag.second + u")[1]"_s;
}
- QString doc = getDocumentation(xquery, funcQuery, DocModificationList());
+ QString doc = getDocumentation(xquery, funcQuery,
+ DocParser::getXpathDocModifications(func, metaClass));
if (doc.isEmpty()) {
qCWarning(lcShibokenDoc, "%s",
- qPrintable(msgCannotFindDocumentation(doxyFilePath, func.data(),
+ qPrintable(msgCannotFindDocumentation(doxyFilePath, func.get(),
funcQuery)));
} else {
funcDoc.setValue(doc, tag.first);
}
}
- qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(funcDoc);
+ std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(funcDoc);
isProperty = false;
}
@@ -204,12 +206,12 @@ Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){
qCWarning(lcShibokenDoc).noquote().nospace()
<< "Can't find doxygen XML file for module " << name << ", tried: "
<< QDir::toNativeSeparators(sourceFile);
- return Documentation();
+ return {};
}
QString errorMessage;
XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage);
- if (xquery.isNull()) {
+ if (!xquery) {
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
return {};
}
diff --git a/sources/shiboken6/ApiExtractor/doxygenparser.h b/sources/shiboken6/ApiExtractor/doxygenparser.h
index ea1883d12..4f6a9e53c 100644
--- a/sources/shiboken6/ApiExtractor/doxygenparser.h
+++ b/sources/shiboken6/ApiExtractor/doxygenparser.h
@@ -10,7 +10,7 @@ class DoxygenParser : public DocParser
{
public:
DoxygenParser() = default;
- void fillDocumentation(AbstractMetaClass *metaClass) override;
+ void fillDocumentation(const AbstractMetaClassPtr &metaClass) override;
Documentation retrieveModuleDocumentation() override;
Documentation retrieveModuleDocumentation(const QString& name) override;
};
diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp
index f2d5074b7..2421ae527 100644
--- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp
+++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.cpp
@@ -5,9 +5,9 @@
#include "abstractmetalang.h"
#include "namespacetypeentry.h"
-const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const
+AbstractMetaClassCPtr EnclosingClassMixin::targetLangEnclosingClass() const
{
- auto result = m_enclosingClass;
+ auto result = m_enclosingClass.lock();
while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry()))
result = result->enclosingClass();
return result;
diff --git a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h
index 31aeb9285..8d735d5ec 100644
--- a/sources/shiboken6/ApiExtractor/enclosingclassmixin.h
+++ b/sources/shiboken6/ApiExtractor/enclosingclassmixin.h
@@ -4,16 +4,21 @@
#ifndef ENCLOSINGCLASSMIXIN_H
#define ENCLOSINGCLASSMIXIN_H
+#include "abstractmetalang_typedefs.h"
+
class AbstractMetaClass;
class EnclosingClassMixin {
public:
- const AbstractMetaClass *enclosingClass() const { return m_enclosingClass; }
- void setEnclosingClass(const AbstractMetaClass *cls) { m_enclosingClass = cls; }
- const AbstractMetaClass *targetLangEnclosingClass() const;
+
+ const AbstractMetaClassCPtr enclosingClass() const
+ { return m_enclosingClass.lock(); }
+ void setEnclosingClass(const AbstractMetaClassCPtr &cls)
+ { m_enclosingClass = cls; }
+ AbstractMetaClassCPtr targetLangEnclosingClass() const;
private:
- const AbstractMetaClass *m_enclosingClass = nullptr;
+ std::weak_ptr<const AbstractMetaClass> m_enclosingClass;
};
#endif // ENCLOSINGCLASSMIXIN_H
diff --git a/sources/shiboken6/ApiExtractor/enumtypeentry.h b/sources/shiboken6/ApiExtractor/enumtypeentry.h
index b67e5ad84..3360d7db5 100644
--- a/sources/shiboken6/ApiExtractor/enumtypeentry.h
+++ b/sources/shiboken6/ApiExtractor/enumtypeentry.h
@@ -4,33 +4,42 @@
#ifndef ENUMTYPEENTRY_H
#define ENUMTYPEENTRY_H
-#include "typesystem.h"
+#include "configurabletypeentry.h"
+#include "typesystem_enums.h"
class EnumTypeEntryPrivate;
-class EnumValueTypeEntry;
-class FlagsTypeEntry;
-class EnumTypeEntry : public TypeEntry
+// EnumTypeEntry is configurable for global enums only
+class EnumTypeEntry : public ConfigurableTypeEntry
{
public:
explicit EnumTypeEntry(const QString &entryName,
const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
+
+ TypeSystem::PythonEnumType pythonEnumType() const;
+ void setPythonEnumType(TypeSystem::PythonEnumType t);
QString targetLangQualifier() const;
QString qualifier() const;
- const EnumValueTypeEntry *nullValue() const;
- void setNullValue(const EnumValueTypeEntry *n);
+ EnumValueTypeEntryCPtr nullValue() const;
+ void setNullValue(const EnumValueTypeEntryCPtr &n);
+
+ void setFlags(const FlagsTypeEntryPtr &flags);
+ FlagsTypeEntryPtr flags() const;
- void setFlags(FlagsTypeEntry *flags);
- FlagsTypeEntry *flags() const;
+ QString cppType() const;
+ void setCppType(const QString &t);
bool isEnumValueRejected(const QString &name) const;
void addEnumValueRejection(const QString &name);
QStringList enumValueRejections() const;
+ QString docFile() const;
+ void setDocFile(const QString &df);
+
TypeEntry *clone() const override;
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
diff --git a/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h b/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h
index 730631b0a..006b84e0a 100644
--- a/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h
+++ b/sources/shiboken6/ApiExtractor/enumvaluetypeentry.h
@@ -16,11 +16,11 @@ class EnumValueTypeEntry : public TypeEntry
{
public:
explicit EnumValueTypeEntry(const QString& name, const QString& value,
- const EnumTypeEntry* enclosingEnum,
+ const EnumTypeEntryCPtr &enclosingEnum,
bool isScopedEnum, const QVersionNumber &vr);
QString value() const;
- const EnumTypeEntry* enclosingEnum() const;
+ EnumTypeEntryCPtr enclosingEnum() const;
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/fileout.cpp b/sources/shiboken6/ApiExtractor/fileout.cpp
index e6770aabc..6f9ec4d8a 100644
--- a/sources/shiboken6/ApiExtractor/fileout.cpp
+++ b/sources/shiboken6/ApiExtractor/fileout.cpp
@@ -42,20 +42,20 @@ FileOut::~FileOut()
}
}
-static QList<int> lcsLength(const QByteArrayList &a, const QByteArrayList &b)
+static QList<qsizetype> lcsLength(const QByteArrayList &a, const QByteArrayList &b)
{
- const int height = a.size() + 1;
- const int width = b.size() + 1;
+ const auto height = a.size() + 1;
+ const auto width = b.size() + 1;
- QList<int> res(width * height, 0);
+ QList<qsizetype> res(width * height, 0);
- for (int row = 1; row < height; row++) {
- for (int col = 1; col < width; col++) {
- if (a[row-1] == b[col-1])
- res[width * row + col] = res[width * (row-1) + col-1] + 1;
+ for (qsizetype row = 1; row < height; row++) {
+ for (qsizetype col = 1; col < width; col++) {
+ if (a.at(row - 1) == b.at(col - 1))
+ res[width * row + col] = res[width * (row - 1) + col - 1] + 1;
else
- res[width * row + col] = qMax(res[width * row + col-1],
- res[width * (row-1) + col]);
+ res[width * row + col] = qMax(res[width * row + col - 1],
+ res[width * (row - 1) + col]);
}
}
return res;
@@ -70,8 +70,8 @@ enum Type {
struct Unit
{
Type type;
- int start;
- int end;
+ qsizetype start;
+ qsizetype end;
void print(const QByteArrayList &a, const QByteArrayList &b) const;
};
@@ -81,33 +81,33 @@ void Unit::print(const QByteArrayList &a, const QByteArrayList &b) const
switch (type) {
case Unchanged:
if ((end - start) > 9) {
- for (int i = start; i <= start + 2; i++)
+ for (auto i = start; i <= start + 2; ++i)
std::printf(" %s\n", a.at(i).constData());
std::printf("%s=\n= %d more lines\n=%s\n",
- colorInfo, end - start - 6, colorReset);
- for (int i = end - 2; i <= end; i++)
+ colorInfo, int(end - start - 6), colorReset);
+ for (auto i = end - 2; i <= end; ++i)
std::printf(" %s\n", a.at(i).constData());
} else {
- for (int i = start; i <= end; i++)
+ for (auto i = start; i <= end; ++i)
std::printf(" %s\n", a.at(i).constData());
}
break;
case Add:
std::fputs(colorAdd, stdout);
- for (int i = start; i <= end; i++)
+ for (auto i = start; i <= end; ++i)
std::printf("+ %s\n", b.at(i).constData());
std::fputs(colorReset, stdout);
break;
case Delete:
std::fputs(colorDelete, stdout);
- for (int i = start; i <= end; i++)
+ for (auto i = start; i <= end; ++i)
std::printf("- %s\n", a.at(i).constData());
std::fputs(colorReset, stdout);
break;
}
}
-static void unitAppend(Type type, int pos, QList<Unit> *units)
+static void unitAppend(Type type, qsizetype pos, QList<Unit> *units)
{
if (!units->isEmpty() && units->last().type == type)
units->last().end = pos;
@@ -115,9 +115,9 @@ static void unitAppend(Type type, int pos, QList<Unit> *units)
units->append(Unit{type, pos, pos});
}
-static QList<Unit> diffHelper(const QList<int> &lcs,
- const QByteArrayList &a, const QByteArrayList &b,
- int row, int col)
+static QList<Unit> diffHelper(const QList<qsizetype> &lcs,
+ const QByteArrayList &a, const QByteArrayList &b,
+ qsizetype row, qsizetype col)
{
if (row > 0 && col > 0 && a.at(row - 1) == b.at(col - 1)) {
QList<Unit> result = diffHelper(lcs, a, b, row - 1, col - 1);
@@ -125,7 +125,7 @@ static QList<Unit> diffHelper(const QList<int> &lcs,
return result;
}
- const int width = b.size() + 1;
+ const auto width = b.size() + 1;
if (col > 0
&& (row == 0 || lcs.at(width * row + col -1 ) >= lcs.at(width * (row - 1) + col))) {
QList<Unit> result = diffHelper(lcs, a, b, row, col - 1);
@@ -175,7 +175,7 @@ FileOut::State FileOut::done()
if (!FileOut::m_dryRun) {
QDir dir(info.absolutePath());
if (!dir.mkpath(dir.absolutePath())) {
- const QString message = QStringLiteral("Unable to create directory '%1'")
+ const QString message = QString::fromLatin1("Unable to create directory '%1'")
.arg(QDir::toNativeSeparators(dir.absolutePath()));
throw Exception(message);
}
diff --git a/sources/shiboken6/ApiExtractor/fileout.h b/sources/shiboken6/ApiExtractor/fileout.h
index d3f1b7b1f..b11ad1e20 100644
--- a/sources/shiboken6/ApiExtractor/fileout.h
+++ b/sources/shiboken6/ApiExtractor/fileout.h
@@ -14,7 +14,7 @@ class FileOut
{
QByteArray m_buffer;
public:
- Q_DISABLE_COPY(FileOut)
+ Q_DISABLE_COPY_MOVE(FileOut)
enum State { Unchanged, Success };
diff --git a/sources/shiboken6/ApiExtractor/flagstypeentry.h b/sources/shiboken6/ApiExtractor/flagstypeentry.h
index 172407d1b..6eddcd12b 100644
--- a/sources/shiboken6/ApiExtractor/flagstypeentry.h
+++ b/sources/shiboken6/ApiExtractor/flagstypeentry.h
@@ -9,11 +9,12 @@
class EnumTypeEntry;
class FlagsTypeEntryPrivate;
+// FlagsTypeEntry is configurable for global flags only
class FlagsTypeEntry : public TypeEntry
{
public:
explicit FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
QString originalName() const;
void setOriginalName(const QString &s);
@@ -21,8 +22,8 @@ public:
QString flagsName() const;
void setFlagsName(const QString &name);
- EnumTypeEntry *originator() const;
- void setOriginator(EnumTypeEntry *e);
+ EnumTypeEntryPtr originator() const;
+ void setOriginator(const EnumTypeEntryPtr &e);
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/functiontypeentry.h b/sources/shiboken6/ApiExtractor/functiontypeentry.h
index 3d7399931..53aa1fad6 100644
--- a/sources/shiboken6/ApiExtractor/functiontypeentry.h
+++ b/sources/shiboken6/ApiExtractor/functiontypeentry.h
@@ -13,14 +13,14 @@ class FunctionTypeEntry : public TypeEntry
public:
explicit FunctionTypeEntry(const QString& name, const QString& signature,
const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
const QStringList &signatures() const;
bool hasSignature(const QString& signature) const;
void addSignature(const QString& signature);
- TypeSystem::SnakeCase snakeCase() const;
- void setSnakeCase(TypeSystem::SnakeCase sc);
+ QString docFile() const;
+ void setDocFile(const QString &df);
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/header_paths.h b/sources/shiboken6/ApiExtractor/header_paths.h
index ca00a5360..af4a768e8 100644
--- a/sources/shiboken6/ApiExtractor/header_paths.h
+++ b/sources/shiboken6/ApiExtractor/header_paths.h
@@ -6,7 +6,6 @@
#include <QtCore/QByteArray>
#include <QtCore/QList>
-#include <QtCore/QString>
enum class HeaderType
{
diff --git a/sources/shiboken6/ApiExtractor/icecc.cmake b/sources/shiboken6/ApiExtractor/icecc.cmake
index b2bf071aa..fa8d3b7cf 100644
--- a/sources/shiboken6/ApiExtractor/icecc.cmake
+++ b/sources/shiboken6/ApiExtractor/icecc.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include (CMakeForceCompiler)
option(ENABLE_ICECC "Enable icecc checking, for distributed compilation")
if (ENABLE_ICECC)
diff --git a/sources/shiboken6/ApiExtractor/include.cpp b/sources/shiboken6/ApiExtractor/include.cpp
index 634945ed8..aee6b7337 100644
--- a/sources/shiboken6/ApiExtractor/include.cpp
+++ b/sources/shiboken6/ApiExtractor/include.cpp
@@ -24,9 +24,15 @@ QString Include::toString() const
return u"import "_s + m_name + u';';
}
-size_t qHash(const Include& inc)
+Qt::strong_ordering compareThreeWay(const Include &lhs, const Include &rhs) noexcept
{
- return qHash(inc.m_name);
+ if (lhs.m_type < rhs.m_type)
+ return Qt::strong_ordering::less;
+ if (lhs.m_type > rhs.m_type)
+ return Qt::strong_ordering::greater;
+ if (auto c = lhs.m_name.compare(rhs.m_name))
+ return c < 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater;
+ return Qt::strong_ordering::equal;
}
QTextStream& operator<<(QTextStream& out, const Include& g)
@@ -50,7 +56,7 @@ TextStream& operator<<(TextStream &out, const IncludeGroup& g)
out << "\n// " << g.title << "\n";
auto includes = g.includes;
std::sort(includes.begin(), includes.end());
- for (const Include &inc : qAsConst(includes))
+ for (const Include &inc : std::as_const(includes))
out << inc.toString() << '\n';
}
return out;
diff --git a/sources/shiboken6/ApiExtractor/include.h b/sources/shiboken6/ApiExtractor/include.h
index 6b463a230..875a941f9 100644
--- a/sources/shiboken6/ApiExtractor/include.h
+++ b/sources/shiboken6/ApiExtractor/include.h
@@ -4,6 +4,8 @@
#ifndef INCLUDE_H
#define INCLUDE_H
+#include <QtCore/QtCompare>
+#include <QtCore/QHashFunctions>
#include <QtCore/QString>
#include <QtCore/QList>
@@ -42,23 +44,25 @@ public:
QString toString() const;
- bool operator<(const Include& other) const
+ int compare(const Include &rhs) const;
+
+private:
+ friend size_t qHash(Include &inc, size_t seed = 0) noexcept
{
- return m_name < other.m_name;
+ return qHashMulti(seed, inc.m_type, inc.m_name);
}
-
- bool operator==(const Include& other) const
+ friend bool comparesEqual(const Include &lhs, const Include &rhs) noexcept
{
- return m_type == other.m_type && m_name == other.m_name;
+ return lhs.m_type == rhs.m_type && lhs.m_name == rhs.m_name;
}
+ friend Qt::strong_ordering compareThreeWay(const Include &lhs,
+ const Include &rhs) noexcept;
+ Q_DECLARE_STRONGLY_ORDERED(Include)
- friend size_t qHash(const Include&);
- private:
- IncludeType m_type = IncludePath;
- QString m_name;
+ IncludeType m_type = IncludePath;
+ QString m_name;
};
-size_t qHash(const Include& inc);
QTextStream& operator<<(QTextStream& out, const Include& include);
TextStream& operator<<(TextStream& out, const Include& include);
#ifndef QT_NO_DEBUG_STREAM
@@ -71,6 +75,17 @@ struct IncludeGroup
{
QString title;
IncludeList includes;
+
+ void append(const Include &include)
+ {
+ IncludeGroup::appendInclude(include, &includes);
+ }
+
+ static void appendInclude(const Include &include, IncludeList *list)
+ {
+ if (include.isValid() && !list->contains(include))
+ list->append(include);
+ }
};
TextStream& operator<<(TextStream &out, const IncludeGroup& include);
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index e91aef5cc..b1f0b240e 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -16,7 +16,6 @@
#include "qtcompat.h"
-#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
@@ -25,11 +24,25 @@
using namespace Qt::StringLiterals;
-static inline QString colonColon() { return QStringLiteral("::"); }
-
// abstractmetabuilder.cpp
-QString msgNoFunctionForModification(const AbstractMetaClass *klass,
+static QTextStream &operator<<(QTextStream &s, Access a)
+{
+ switch (a) {
+ case Access::Public:
+ s << "public";
+ break;
+ case Access::Protected:
+ s << "protected";
+ break;
+ case Access::Private:
+ s << "private";
+ break;
+ }
+ return s;
+}
+
+QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass,
const QString &signature,
const QString &originalSignature,
const QStringList &possibleSignatures,
@@ -49,8 +62,8 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass,
str << " " << s << '\n';
} else if (!allFunctions.isEmpty()) {
str << "\n No candidates were found. Member functions:\n";
- const int maxCount = qMin(10, allFunctions.size());
- for (int f = 0; f < maxCount; ++f)
+ const auto maxCount = qMin(qsizetype(10), allFunctions.size());
+ for (qsizetype f = 0; f < maxCount; ++f)
str << " " << allFunctions.at(f)->minimalSignature() << '\n';
if (maxCount < allFunctions.size())
str << " ...\n";
@@ -79,7 +92,7 @@ QString msgTypeModificationFailed(const QString &type, int n,
str << "type of argument " << n;
str << " of ";
- if (auto *c = func->ownerClass())
+ if (auto c = func->ownerClass())
str << c->name() << "::";
str << func->signature() << " to \"" << type << "\": " << why;
return result;
@@ -113,7 +126,7 @@ QString msgArgumentRemovalFailed(const AbstractMetaFunction *func, int n,
QString result;
QTextStream str(&result);
str << "Unable to remove argument " << n << " of ";
- if (auto *c = func->ownerClass())
+ if (auto c = func->ownerClass())
str << c->name() << "::";
str << func->signature() << ": " << why;
return result;
@@ -126,7 +139,7 @@ static void msgFormatEnumType(Stream &str,
{
switch (enumItem->enumKind()) {
case CEnum:
- str << "Enum '" << enumItem->qualifiedName().join(colonColon()) << '\'';
+ str << "Enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
break;
case AnonymousEnum: {
const EnumeratorList &values = enumItem->enumerators();
@@ -149,7 +162,7 @@ static void msgFormatEnumType(Stream &str,
}
break;
case EnumClass:
- str << "Scoped enum '" << enumItem->qualifiedName().join(colonColon()) << '\'';
+ str << "Scoped enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
break;
}
if (!className.isEmpty())
@@ -157,7 +170,7 @@ static void msgFormatEnumType(Stream &str,
}
static void formatAddedFuncError(const QString &addedFuncName,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
QTextStream &str)
{
if (context) {
@@ -173,12 +186,12 @@ static void formatAddedFuncError(const QString &addedFuncName,
QString msgAddedFunctionInvalidArgType(const QString &addedFuncName,
const QStringList &typeName,
int pos, const QString &why,
- const AbstractMetaClass *context)
+ const AbstractMetaClassCPtr &context)
{
QString result;
QTextStream str(&result);
formatAddedFuncError(addedFuncName, context, str);
- str << "Unable to translate type \"" << typeName.join(colonColon())
+ str << "Unable to translate type \"" << typeName.join(u"::"_s)
<< "\" of argument " << pos << " of added function \""
<< addedFuncName << "\": " << why;
return result;
@@ -186,18 +199,18 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName,
QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName,
const QStringList &typeName, const QString &why,
- const AbstractMetaClass *context)
+ const AbstractMetaClassCPtr &context)
{
QString result;
QTextStream str(&result);
formatAddedFuncError(addedFuncName, context, str);
- str << "Unable to translate return type \"" << typeName.join(colonColon())
+ str << "Unable to translate return type \"" << typeName.join(u"::"_s)
<< "\" of added function \"" << addedFuncName << "\": "
<< why;
return result;
}
-QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context,
+QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context,
int n, const QString &className,
const AbstractMetaFunction *f)
{
@@ -210,7 +223,7 @@ QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context,
return result;
}
-QString msgClassOfEnumNotFound(const EnumTypeEntry *entry)
+QString msgClassOfEnumNotFound(const EnumTypeEntryCPtr &entry)
{
QString result;
QTextStream str(&result);
@@ -227,13 +240,14 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem,
QTextStream str(&result);
str << enumItem->sourceLocation();
msgFormatEnumType(str, enumItem, className);
- str << " does not have a type entry";
+ str << " does not have a type entry (type systems: "
+ << TypeDatabase::instance()->loadedTypeSystemNames() << ')';
return result;
}
QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
const QString &className,
- const TypeEntry *t)
+ const TypeEntryCPtr &t)
{
QString result;
QDebug debug(&result); // Use the debug operator for TypeEntry::Type
@@ -251,11 +265,17 @@ QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item,
QString result;
QTextStream str(&result);
str << item->sourceLocation() << "namespace '" << fullName
- << "' does not have a type entry";
+ << "' does not have a type entry (type systems: "
+ << TypeDatabase::instance()->loadedTypeSystemNames() << ')';
return result;
}
-QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te)
+QString msgNamespaceNotFound(const QString &name)
+{
+ return u"namespace '"_s + name + u"' not found."_s;
+}
+
+QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntryCList &te)
{
QString result = u"Ambiguous types of varying types found for \""_s + qualifiedName
+ u"\": "_s;
@@ -263,7 +283,7 @@ QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEn
return result;
}
-QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te)
+QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntryCList &te)
{
QString result = u"Ambiguous types found for \""_s + qualifiedName
+ u"\": "_s;
@@ -297,11 +317,13 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem,
{
QString result;
QTextStream str(&result);
- str << functionItem->sourceLocation() << "skipping ";
- if (functionItem->isAbstract())
+ str << functionItem->sourceLocation() << "skipping "
+ << functionItem->accessPolicy() << ' ';
+ const bool isAbstract = functionItem->attributes().testFlag(FunctionAttribute::Abstract);
+ if (isAbstract)
str << "abstract ";
str << "function '" << signature << "', " << why;
- if (functionItem->isAbstract()) {
+ if (isAbstract) {
str << "\nThis will lead to compilation errors due to not "
"being able to instantiate the wrapper.";
}
@@ -319,7 +341,7 @@ QString msgShadowingFunction(const AbstractMetaFunction *f1,
return result;
}
-QString msgSignalOverloaded(const AbstractMetaClass *c,
+QString msgSignalOverloaded(const AbstractMetaClassCPtr &c,
const AbstractMetaFunction *f)
{
QString result;
@@ -334,24 +356,31 @@ QString msgSkippingField(const VariableModelItem &field, const QString &classNam
{
QString result;
QTextStream str(&result);
- str << field->sourceLocation() << "skipping field '" << className
- << "::" << field->name() << "' with unmatched type '" << type << '\'';
+ str << field->sourceLocation() << "skipping " << field->accessPolicy()
+ << " field '" << className << "::" << field->name()
+ << "' with unmatched type '" << type << '\'';
return result;
}
static const char msgCompilationError[] =
"This could potentially lead to compilation errors.";
-QString msgTypeNotDefined(const TypeEntry *entry)
+QString msgTypeNotDefined(const TypeEntryCPtr &entry)
{
QString result;
QTextStream str(&result);
+ const bool hasConfigCondition = entry->isComplex()
+ && std::static_pointer_cast<const ConfigurableTypeEntry>(entry)->hasConfigCondition();
str << entry->sourceLocation() << "type '" <<entry->qualifiedCppName()
- << "' is specified in typesystem, but not defined. " << msgCompilationError;
+ << "' is specified in typesystem, but not defined";
+ if (hasConfigCondition)
+ str << " (disabled by configuration?).";
+ else
+ str << ". " << msgCompilationError;
return result;
}
-QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte,
+QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte,
const QString &signature,
const QStringList &candidates)
{
@@ -367,18 +396,19 @@ QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte,
QString msgStrippingArgument(const FunctionModelItem &f, int i,
const QString &originalSignature,
- const ArgumentModelItem &arg)
+ const ArgumentModelItem &arg,
+ const QString &reason)
{
QString result;
QTextStream str(&result);
str << f->sourceLocation() << "Stripping argument #" << (i + 1) << " of "
<< originalSignature << " due to unmatched type \""
<< arg->type().toString() << "\" with default expression \""
- << arg->defaultValueExpression() << "\".";
+ << arg->defaultValueExpression() << "\": " << reason;
return result;
}
-QString msgEnumNotDefined(const EnumTypeEntry *t)
+QString msgEnumNotDefined(const EnumTypeEntryCPtr &t)
{
QString result;
QTextStream str(&result);
@@ -387,7 +417,7 @@ QString msgEnumNotDefined(const EnumTypeEntry *t)
return result;
}
-QString msgUnknownBase(const AbstractMetaClass *metaClass,
+QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass,
const QString &baseClassName)
{
QString result;
@@ -397,7 +427,7 @@ QString msgUnknownBase(const AbstractMetaClass *metaClass,
return result;
}
-QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass,
+QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass,
const QString &baseClassName)
{
QString result;
@@ -451,6 +481,21 @@ QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &s
+ u"\" for instantiation of \""_s +smartPointerType + u"\"."_s;
}
+QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass,
+ const TypeInfo &info,
+ const QString &what)
+{
+ return "While inheriting template "_L1 + subclass->name()
+ + " from "_L1 + info.toString() + ": "_L1 + what;
+}
+
+QString msgIgnoringTemplateParameter(const QString &typeName,
+ const char *why)
+{
+ return "Ignoring template parameter "_L1 + typeName +
+ ": "_L1 + QLatin1StringView(why);
+}
+
QString msgInvalidSmartPointerType(const TypeInfo &i)
{
return u"Invalid smart pointer type \""_s +i.toString() + u"\"."_s;
@@ -506,7 +551,7 @@ QString msgPropertyExists(const QString &className, const QString &name)
+ name + u"\" (defined by Q_PROPERTY)."_s;
}
-QString msgFunctionVisibilityModified(const AbstractMetaClass *c,
+QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c,
const AbstractMetaFunction *f)
{
QString result;
@@ -516,7 +561,7 @@ QString msgFunctionVisibilityModified(const AbstractMetaClass *c,
return result;
}
-QString msgUsingMemberClassNotFound(const AbstractMetaClass *c,
+QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c,
const QString &baseClassName,
const QString &memberName)
{
@@ -582,23 +627,25 @@ QString msgFallbackForDocumentation(const QString &fileName,
}
QString msgCannotFindDocumentation(const QString &fileName,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaEnum &e,
const QString &query)
{
- return msgCannotFindDocumentation(fileName, "enum",
- metaClass->name() + u"::"_s + e.name(),
- query);
+ QString name = e.name();
+ if (metaClass != nullptr)
+ name.prepend(metaClass->name() + "::"_L1);
+ return msgCannotFindDocumentation(fileName, "enum", name, query);
}
QString msgCannotFindDocumentation(const QString &fileName,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaField &f,
const QString &query)
{
- return msgCannotFindDocumentation(fileName, "field",
- metaClass->name() + u"::"_s + f.name(),
- query);
+ QString name = f.name();
+ if (metaClass != nullptr)
+ name.prepend(metaClass->name() + "::"_L1);
+ return msgCannotFindDocumentation(fileName, "field", name, query);
}
QString msgXpathDocModificationError(const DocModificationList& mods,
@@ -626,13 +673,13 @@ QString msgXpathDocModificationError(const DocModificationList& mods,
QString msgCannotOpenForReading(const QFile &f)
{
- return QStringLiteral("Failed to open file '%1' for reading: %2")
+ return QString::fromLatin1("Failed to open file '%1' for reading: %2")
.arg(QDir::toNativeSeparators(f.fileName()), f.errorString());
}
QString msgCannotOpenForWriting(const QFile &f)
{
- return QStringLiteral("Failed to open file '%1' for writing: %2")
+ return QString::fromLatin1("Failed to open file '%1' for writing: %2")
.arg(QDir::toNativeSeparators(f.fileName()), f.errorString());
}
@@ -654,36 +701,19 @@ QString msgCannotUseEnumAsInt(const QString &name)
"Compilation errors may occur when used as a function argument."_s;
}
-QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType)
-{
- QString result;
- QTextStream str(&result);
- str << "Types of receiver variable ('" << varType
- << "') and %%CONVERTTOCPP type system variable ('" << conversionType
- << "') differ";
- QString strippedVarType = varType;
- QString strippedConversionType = conversionType;
- TypeInfo::stripQualifiers(&strippedVarType);
- TypeInfo::stripQualifiers(&strippedConversionType);
- if (strippedVarType == strippedConversionType)
- str << " in qualifiers. Please make sure the type is a distinct token";
- str << '.';
- return result;
-}
-
-QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *te)
+QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &te)
{
return u"Getter \""_s + te->getter() + u"()\" of smart pointer \""_s
+ te->name() + u"\" not found."_s;
}
-QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m)
+QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, const QString &m)
{
return u"Method \""_s + m + u"()\" of smart pointer \""_s
+ te->name() + u"\" not found."_s;
}
-QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name)
+QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name)
{
return u"Method \""_s + name + u"\" not found in class "_s
+ klass->name() + u'.';
@@ -691,18 +721,12 @@ QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name)
// main.cpp
-QString msgLeftOverArguments(const QVariantMap &remainingArgs)
+QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV)
{
QString message;
QTextStream str(&message);
- str << "shiboken: Called with wrong arguments:";
- for (auto it = remainingArgs.cbegin(), end = remainingArgs.cend(); it != end; ++it) {
- str << ' ' << it.key();
- const QString value = it.value().toString();
- if (!value.isEmpty())
- str << ' ' << value;
- }
- str << "\nCommand line: " << QCoreApplication::arguments().join(u' ');
+ str << "shiboken: Unprocessed arguments: " << remainingArgs
+ << "\nCommand line: " << argV.join(u' ');
return message;
}
@@ -723,13 +747,13 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName,
<< "\". Cyclic functions:";
for (const auto &c : cyclic)
str << ' ' << c->signature();
- if (const int count = involvedConversions.size()) {
+ if (const auto count = involvedConversions.size()) {
str << " Implicit conversions (" << count << "): ";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
str << ", \"";
str << involvedConversions.at(i)->signature() << '"';
- if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass())
+ if (const auto c = involvedConversions.at(i)->implementingClass())
str << '(' << c->name() << ')';
}
}
@@ -738,14 +762,14 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName,
// shibokengenerator.cpp
-QString msgClassNotFound(const TypeEntry *t)
+QString msgClassNotFound(const TypeEntryCPtr &t)
{
return u"Could not find class \""_s
+ t->qualifiedCppName()
+ u"\" in the code model. Maybe it is forward declared?"_s;
}
-QString msgEnclosingClassNotFound(const TypeEntry *t)
+QString msgEnclosingClassNotFound(const TypeEntryCPtr &t)
{
QString result;
QTextStream str(&result);
@@ -754,11 +778,11 @@ QString msgEnclosingClassNotFound(const TypeEntry *t)
return result;
}
-QString msgUnknownOperator(const AbstractMetaFunction* func)
+QString msgUnknownOperator(const AbstractMetaFunction *func)
{
QString result = u"Unknown operator: \""_s + func->originalName()
+ u'"';
- if (const AbstractMetaClass *c = func->implementingClass())
+ if (const auto c = func->implementingClass())
result += u" in class: "_s + c->name();
return result;
}
@@ -769,7 +793,7 @@ QString msgWrongIndex(const char *varName, const QString &capture,
QString result;
QTextStream str(&result);
str << "Wrong index for " << varName << " variable (" << capture << ") on ";
- if (const AbstractMetaClass *c = func->implementingClass())
+ if (const auto c = func->implementingClass())
str << c->name() << "::";
str << func->signature();
return result;
@@ -811,17 +835,17 @@ QString msgRejectReason(const TypeRejection &r, const QString &needle)
QTextStream str(&result);
switch (r.matchType) {
case TypeRejection::ExcludeClass:
- str << " matches class exclusion \"" << r.className.pattern() << '"';
+ str << "matches class exclusion \"" << r.className.pattern() << '"';
break;
case TypeRejection::Function:
case TypeRejection::Field:
case TypeRejection::Enum:
- str << " matches class \"" << r.className.pattern() << "\" and \""
+ str << "matches class \"" << r.className.pattern() << "\" and \""
<< r.pattern.pattern() << '"';
break;
case TypeRejection::ArgumentType:
case TypeRejection::ReturnType:
- str << " matches class \"" << r.className.pattern() << "\" and \""
+ str << "matches class \"" << r.className.pattern() << "\" and \""
<< needle << "\" matches \"" << r.pattern.pattern() << '"';
break;
}
@@ -874,6 +898,21 @@ QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel)
return result;
}
+QString msgSnippetError(const QString &context, const char *what)
+{
+ return "Error processing code snippet of "_L1 + context
+ + ": "_L1 + QString::fromUtf8(what);
+}
+
+QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName)
+{
+ QString result;
+ QTextStream(&result) << "Unable to resolve typedef \"" << sourceType
+ << "\": Could not find a value, container, object or smart pointer type named \""
+ << sourceName << "\".";
+ return result;
+}
+
// cppgenerator.cpp
QString msgPureVirtualFunctionRemoved(const AbstractMetaFunction *f)
@@ -917,17 +956,42 @@ QString msgInvalidTargetLanguageApiName(const QString &name)
+ name + u"\"."_s;
}
-QString msgUnknownCheckFunction(const TypeEntry *t)
+QString msgUnknownCheckFunction(const TypeEntryCPtr &t)
{
return u"Unknown check function for type: '"_s
+ t->qualifiedCppName() + u"'."_s;
}
QString msgArgumentClassNotFound(const AbstractMetaFunctionCPtr &func,
- const TypeEntry *t)
+ const TypeEntryCPtr &t)
{
QString result;
QTextStream(&result) << "Internal Error: Class \"" << t->qualifiedCppName()
<< "\" for \"" << func->classQualifiedSignature() << "\" not found!";
return result;
}
+
+QString msgMissingCustomConversion(const TypeEntryCPtr &t)
+{
+ QString result;
+ QTextStream(&result) << "Entry \"" << t->qualifiedCppName()
+ << "\" is missing a custom conversion.";
+ return result;
+}
+
+QString msgUnknownArrayPointerConversion(const QString &s)
+{
+ return u"Warning: Falling back to pointer conversion for unknown array type \""_s
+ + s + u"\""_s;
+}
+
+QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker)
+{
+ return u"First line of project file \""_s + QDir::toNativeSeparators(name)
+ + u"\" must be the string \""_s + QString::fromLatin1(startMarker) + u"\"."_s;
+}
+
+QString msgInvalidLanguageLevel(const QString &l)
+{
+ return u"Invalid argument for language level: \""_s + l + u"\"."_s;
+}
diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h
index 4a23c6487..e3f582b49 100644
--- a/sources/shiboken6/ApiExtractor/messages.h
+++ b/sources/shiboken6/ApiExtractor/messages.h
@@ -6,11 +6,10 @@
#include "abstractmetalang_typedefs.h"
#include "parser/codemodel_fwd.h"
+#include "modifications_typedefs.h"
#include "typesystem_typedefs.h"
-#include <QtCore/QMap>
#include <QtCore/QString>
-#include <QtCore/QList>
class EnumTypeEntry;
class FunctionTypeEntry;
@@ -26,19 +25,19 @@ QT_FORWARD_DECLARE_CLASS(QXmlStreamReader)
QString msgAddedFunctionInvalidArgType(const QString &addedFuncName,
const QStringList &typeName,
int pos, const QString &why,
- const AbstractMetaClass *context = nullptr);
+ const AbstractMetaClassCPtr &context = {});
QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName,
const QStringList &typeName, const QString &why,
- const AbstractMetaClass *context = nullptr);
+ const AbstractMetaClassCPtr &context = {});
-QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClass *context,
+QString msgUnnamedArgumentDefaultExpression(const AbstractMetaClassCPtr &context,
int n, const QString &className,
const AbstractMetaFunction *f);
QString msgArgumentIndexOutOfRange(const AbstractMetaFunction *func, int index);
-QString msgNoFunctionForModification(const AbstractMetaClass *klass,
+QString msgNoFunctionForModification(const AbstractMetaClassCPtr &klass,
const QString &signature,
const QString &originalSignature,
const QStringList &possibleSignatures,
@@ -56,7 +55,7 @@ QString msgArgumentOutOfRange(int number, int minValue, int maxValue);
QString msgArgumentRemovalFailed(const AbstractMetaFunction *func, int n,
const QString &why);
-QString msgClassOfEnumNotFound(const EnumTypeEntry *entry);
+QString msgClassOfEnumNotFound(const EnumTypeEntryCPtr &entry);
QString msgNoEnumTypeEntry(const EnumModelItem &enumItem,
const QString &className);
@@ -64,13 +63,15 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem,
QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
const QString &className,
- const TypeEntry *t);
+ const TypeEntryCPtr &t);
QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item,
const QString &fullName);
-QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te);
-QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te);
+QString msgNamespaceNotFound(const QString &name);
+
+QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntryCList &te);
+QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntryCList &te);
QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n,
const QString &why);
@@ -81,7 +82,7 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem,
QString msgShadowingFunction(const AbstractMetaFunction *f1,
const AbstractMetaFunction *f2);
-QString msgSignalOverloaded(const AbstractMetaClass *c,
+QString msgSignalOverloaded(const AbstractMetaClassCPtr &c,
const AbstractMetaFunction *f);
QString msgSkippingFunction(const FunctionModelItem &functionItem,
@@ -90,22 +91,23 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem,
QString msgSkippingField(const VariableModelItem &field, const QString &className,
const QString &type);
-QString msgTypeNotDefined(const TypeEntry *entry);
+QString msgTypeNotDefined(const TypeEntryCPtr &entry);
-QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte,
+QString msgGlobalFunctionNotDefined(const FunctionTypeEntryCPtr &fte,
const QString &signature,
const QStringList &candidates);
QString msgStrippingArgument(const FunctionModelItem &f, int i,
const QString &originalSignature,
- const ArgumentModelItem &arg);
+ const ArgumentModelItem &arg,
+ const QString &reason);
-QString msgEnumNotDefined(const EnumTypeEntry *t);
+QString msgEnumNotDefined(const EnumTypeEntryCPtr &t);
-QString msgUnknownBase(const AbstractMetaClass *metaClass,
+QString msgUnknownBase(const AbstractMetaClassCPtr &metaClass,
const QString &baseClassName);
-QString msgBaseNotInTypeSystem(const AbstractMetaClass *metaClass,
+QString msgBaseNotInTypeSystem(const AbstractMetaClassCPtr &metaClass,
const QString &baseClassName);
QString msgArrayModificationFailed(const FunctionModelItem &functionItem,
@@ -124,6 +126,10 @@ QString msgUnableToTranslateType(const TypeInfo &typeInfo,
QString msgCannotFindTypeEntry(const QString &t);
QString msgCannotFindTypeEntryForSmartPointer(const QString &t, const QString &smartPointerType);
+QString msgInheritTemplateIssue(const AbstractMetaClassPtr &subclass,
+ const TypeInfo &info, const QString &what);
+QString msgIgnoringTemplateParameter(const QString &typeName,
+ const char *why);
QString msgInvalidSmartPointerType(const TypeInfo &i);
QString msgCannotFindSmartPointerInstantion(const TypeInfo &i);
@@ -139,10 +145,10 @@ QString msgPropertyTypeParsingFailed(const QString &name, const QString &typeNam
const QString &why);
QString msgPropertyExists(const QString &className, const QString &name);
-QString msgFunctionVisibilityModified(const AbstractMetaClass *c,
+QString msgFunctionVisibilityModified(const AbstractMetaClassCPtr &c,
const AbstractMetaFunction *f);
-QString msgUsingMemberClassNotFound(const AbstractMetaClass *c,
+QString msgUsingMemberClassNotFound(const AbstractMetaClassCPtr &c,
const QString &baseClassName,
const QString &memberName);
@@ -163,12 +169,12 @@ QString msgFallbackForDocumentation(const QString &fileName,
const QString &query = {});
QString msgCannotFindDocumentation(const QString &fileName,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaEnum &e,
const QString &query = {});
QString msgCannotFindDocumentation(const QString &fileName,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaField &f,
const QString &query);
@@ -183,15 +189,13 @@ QString msgWriteFailed(const QFile &f, qsizetype size);
QString msgCannotUseEnumAsInt(const QString &name);
-QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType);
-
-QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *);
+QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntryCPtr &);
-QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m);
+QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntryCPtr &te, const QString &m);
-QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name);
+QString msgMethodNotFound(const AbstractMetaClassCPtr &klass, const QString &name);
-QString msgLeftOverArguments(const QVariantMap &remainingArgs);
+QString msgLeftOverArguments(const QString &remainingArgs, const QStringList &argV);
QString msgInvalidVersion(const QString &package, const QString &version);
@@ -209,16 +213,18 @@ QString msgIncorrectlyNestedName(const QString &name);
QString msgCannotFindView(const QString &viewedName, const QString &name);
QString msgCannotFindSnippet(const QString &file, const QString &snippetLabel);
+QString msgSnippetError(const QString &context, const char *what);
+QString msgUnableToResolveTypedef(const QString &sourceType, const QString &sourceName);
QString msgCyclicDependency(const QString &funcName, const QString &graphName,
const AbstractMetaFunctionCList &cyclic,
const AbstractMetaFunctionCList &involvedConversions);
-QString msgClassNotFound(const TypeEntry *t);
+QString msgClassNotFound(const TypeEntryCPtr &t);
-QString msgEnclosingClassNotFound(const TypeEntry *t);
+QString msgEnclosingClassNotFound(const TypeEntryCPtr &t);
-QString msgUnknownOperator(const AbstractMetaFunction* func);
+QString msgUnknownOperator(const AbstractMetaFunction *func);
QString msgWrongIndex(const char *varName, const QString &capture,
const AbstractMetaFunction *func);
@@ -242,9 +248,17 @@ QString msgDuplicateBuiltInTypeEntry(const QString &name);
QString msgDuplicateTypeEntry(const QString &name);
QString msgInvalidTargetLanguageApiName(const QString &name);
-QString msgUnknownCheckFunction(const TypeEntry *t);
+QString msgUnknownCheckFunction(const TypeEntryCPtr &t);
QString msgArgumentClassNotFound(const AbstractMetaFunctionCPtr &func,
- const TypeEntry *t);
+ const TypeEntryCPtr &t);
+
+QString msgMissingCustomConversion(const TypeEntryCPtr &t);
+
+QString msgUnknownArrayPointerConversion(const QString &s);
+
+QString msgMissingProjectFileMarker(const QString &name, const QByteArray &startMarker);
+
+QString msgInvalidLanguageLevel(const QString &l);
#endif // MESSAGES_H
diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp
index 803709162..d876e8035 100644
--- a/sources/shiboken6/ApiExtractor/modifications.cpp
+++ b/sources/shiboken6/ApiExtractor/modifications.cpp
@@ -2,38 +2,18 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "modifications.h"
-#include "modifications_p.h"
#include "codesnip.h"
-#include "exception.h"
-#include "typedatabase.h"
-#include "typeparser.h"
-#include "typesystem.h"
#include "qtcompat.h"
#include <QtCore/QDebug>
+#include <QtCore/QRegularExpression>
#include <algorithm>
#include <limits>
using namespace Qt::StringLiterals;
-static inline QString callOperator() { return QStringLiteral("operator()"); }
-
-// ---------------------- Modification
-QString FunctionModification::accessModifierString() const
-{
- if (isPrivate())
- return u"private"_s;
- if (isProtected())
- return u"protected"_s;
- if (isPublic())
- return u"public"_s;
- if (isFriendly())
- return u"friendly"_s;
- return QString();
-}
-
// ---------------------- FieldModification
class FieldModificationData : public QSharedData
@@ -54,8 +34,8 @@ FieldModification::FieldModification() : d(new FieldModificationData)
FieldModification::FieldModification(const FieldModification &) = default;
FieldModification &FieldModification::operator=(const FieldModification &) = default;
-FieldModification::FieldModification(FieldModification &&) = default;
-FieldModification &FieldModification::operator=(FieldModification &&) = default;
+FieldModification::FieldModification(FieldModification &&) noexcept = default;
+FieldModification &FieldModification::operator=(FieldModification &&) noexcept = default;
FieldModification::~FieldModification() = default;
QString FieldModification::name() const
@@ -140,184 +120,6 @@ void FieldModification::setSnakeCase(TypeSystem::SnakeCase s)
d->snakeCase = s;
}
-// Helpers to split a parameter list of <add-function>, <declare-function>
-// (@ denoting names), like
-// "void foo(QList<X,Y> &@list@ = QList<X,Y>{1,2}, int @b@=5, ...)"
-namespace AddedFunctionParser {
-
-bool Argument::equals(const Argument &rhs) const
-{
- return type == rhs.type && name == rhs.name && defaultValue == rhs.defaultValue;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const Argument &a)
-{
- QDebugStateSaver saver(d);
- d.noquote();
- d.nospace();
- d << "Argument(type=\"" << a.type << '"';
- if (!a.name.isEmpty())
- d << ", name=\"" << a.name << '"';
- if (!a.defaultValue.isEmpty())
- d << ", defaultValue=\"" << a.defaultValue << '"';
- d << ')';
- return d;
-}
-#endif // QT_NO_DEBUG_STREAM
-
-// Helper for finding the end of a function parameter, observing
-// nested template parameters or lists.
-static int parameterTokenEnd(int startPos, QStringView paramString)
-{
- const int end = paramString.size();
- int nestingLevel = 0;
- for (int p = startPos; p < end; ++p) {
- switch (paramString.at(p).toLatin1()) {
- case ',':
- if (nestingLevel == 0)
- return p;
- break;
- case '<': // templates
- case '{': // initializer lists of default values
- case '(': // initialization, function pointers
- case '[': // array dimensions
- ++nestingLevel;
- break;
- case '>':
- case '}':
- case ')':
- case ']':
- --nestingLevel;
- break;
- }
- }
- return end;
-}
-
-// Split a function parameter list into string tokens containing one
-// parameters (including default value, etc).
-static QList<QStringView> splitParameterTokens(QStringView paramString)
-{
- QList<QStringView> result;
- int startPos = 0;
- for ( ; startPos < paramString.size(); ) {
- int end = parameterTokenEnd(startPos, paramString);
- result.append(paramString.mid(startPos, end - startPos).trimmed());
- startPos = end + 1;
- }
- return result;
-}
-
-// Split a function parameter list
-Arguments splitParameters(QStringView paramString, QString *errorMessage)
-{
- Arguments result;
- const QList<QStringView> tokens = splitParameterTokens(paramString);
-
- for (const auto &t : tokens) {
- Argument argument;
- // Check defaultValue, "int @b@=5"
- const int equalPos = t.lastIndexOf(u'=');
- if (equalPos != -1) {
- const int defaultValuePos = equalPos + 1;
- argument.defaultValue =
- t.mid(defaultValuePos, t.size() - defaultValuePos).trimmed().toString();
- }
- QString typeString = (equalPos != -1 ? t.left(equalPos) : t).trimmed().toString();
- // Check @name@
- const int atPos = typeString.indexOf(u'@');
- if (atPos != -1) {
- const int namePos = atPos + 1;
- const int nameEndPos = typeString.indexOf(u'@', namePos);
- if (nameEndPos == -1) {
- if (errorMessage != nullptr) {
- *errorMessage = u"Mismatched @ in \""_s
- + paramString.toString() + u'"';
- }
- return {};
- }
- argument.name = typeString.mid(namePos, nameEndPos - namePos).trimmed();
- typeString.remove(atPos, nameEndPos - atPos + 1);
- }
- argument.type = typeString.trimmed();
- result.append(argument);
- }
-
- return result;
-}
-
-} // namespace AddedFunctionParser
-
-AddedFunction::AddedFunction(const QString &name, const QList<Argument> &arguments,
- const TypeInfo &returnType) :
- m_name(name),
- m_arguments(arguments),
- m_returnType(returnType)
-{
-}
-
-AddedFunction::AddedFunctionPtr
- AddedFunction::createAddedFunction(const QString &signatureIn, const QString &returnTypeIn,
- QString *errorMessage)
-
-{
- errorMessage->clear();
-
- QList<Argument> arguments;
- const TypeInfo returnType = returnTypeIn.isEmpty()
- ? TypeInfo::voidType()
- : TypeParser::parse(returnTypeIn, errorMessage);
- if (!errorMessage->isEmpty())
- return {};
-
- QStringView signature = QStringView{signatureIn}.trimmed();
-
- // Skip past "operator()(...)"
- const int parenSearchStartPos = signature.startsWith(callOperator())
- ? callOperator().size() : 0;
- const int openParenPos = signature.indexOf(u'(', parenSearchStartPos);
- if (openParenPos < 0) {
- return AddedFunctionPtr(new AddedFunction(signature.toString(),
- arguments, returnType));
- }
-
- const QString name = signature.left(openParenPos).trimmed().toString();
- const int closingParenPos = signature.lastIndexOf(u')');
- if (closingParenPos < 0) {
- *errorMessage = u"Missing closing parenthesis"_s;
- return {};
- }
-
- // Check for "foo() const"
- bool isConst = false;
- const int signatureLength = signature.length();
- const int qualifierLength = signatureLength - closingParenPos - 1;
- if (qualifierLength >= 5
- && signature.right(qualifierLength).contains(u"const")) {
- isConst = true;
- }
-
- const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1);
- const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage);
- if (params.isEmpty() && !errorMessage->isEmpty())
- return {};
- for (const auto &p : params) {
- TypeInfo type = p.type == u"..."
- ? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage);
- if (!errorMessage->isEmpty()) {
- errorMessage->prepend(u"Unable to parse added function "_s + signatureIn
- + u": "_s);
- return {};
- }
- arguments.append({type, p.name, p.defaultValue});
- }
-
- AddedFunctionPtr result(new AddedFunction(name, arguments, returnType));
- result->setConstant(isConst);
- return result;
-}
-
// Remove the parameter names enclosed in '@' from an added function signature
// so that it matches the C++ type signature.
static QString removeParameterNames(QString signature)
@@ -372,11 +174,11 @@ QDebug operator<<(QDebug d, const CodeSnip &s)
if (i)
d << ", ";
d << '#' << i << ' ';
- if (f.instance().isNull()) {
+ if (!f.instance()) {
d << '"';
const QString &code = f.code();
const auto lines = QStringView{code}.split(u'\n');
- for (int i = 0, size = lines.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = lines.size(); i < size; ++i) {
if (i)
d << "\\n";
d << lines.at(i).trimmed();
@@ -425,8 +227,8 @@ ArgumentModification::ArgumentModification(int idx) : d(new ArgumentModification
ArgumentModification::ArgumentModification(const ArgumentModification &) = default;
ArgumentModification &ArgumentModification::operator=(const ArgumentModification &) = default;
-ArgumentModification::ArgumentModification(ArgumentModification &&) = default;
-ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) = default;
+ArgumentModification::ArgumentModification(ArgumentModification &&) noexcept = default;
+ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) noexcept = default;
ArgumentModification::~ArgumentModification() = default;
const QString &ArgumentModification::modifiedType() const
@@ -607,7 +409,6 @@ public:
QString m_originalSignature;
QRegularExpression m_signaturePattern;
int m_overloadNumber = TypeSystem::OverloadNumberUnset;
- bool m_thread = false;
bool removed = false;
TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified;
TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified;
@@ -620,8 +421,8 @@ FunctionModification::FunctionModification() : d(new FunctionModificationData)
FunctionModification::FunctionModification(const FunctionModification &) = default;
FunctionModification &FunctionModification::operator=(const FunctionModification &) = default;
-FunctionModification::FunctionModification(FunctionModification &&) = default;
-FunctionModification &FunctionModification::operator=(FunctionModification &&) = default;
+FunctionModification::FunctionModification(FunctionModification &&) noexcept = default;
+FunctionModification &FunctionModification::operator=(FunctionModification &&) noexcept = default;
FunctionModification::~FunctionModification() = default;
void FunctionModification::formatDebug(QDebug &debug) const
@@ -637,8 +438,6 @@ void FunctionModification::formatDebug(QDebug &debug) const
debug << ", renamedToName=\"" << d->renamedToName << '"';
if (d->m_allowThread != TypeSystem::AllowThread::Unspecified)
debug << ", allowThread=" << int(d->m_allowThread);
- if (d->m_thread)
- debug << ", thread";
if (d->m_exceptionHandling != TypeSystem::ExceptionHandling::Unspecified)
debug << ", exceptionHandling=" << int(d->m_exceptionHandling);
if (!d->m_snips.isEmpty())
@@ -741,17 +540,6 @@ void FunctionModification::setSnips(const CodeSnipList &snips)
}
// ---------------------- FunctionModification
-void FunctionModification::setIsThread(bool flag)
-{
- if (d->m_thread != flag)
- d->m_thread = flag;
-}
-
-bool FunctionModification::isThread() const
-{
- return d->m_thread;
-}
-
FunctionModification::AllowThread FunctionModification::allowThread() const
{
return d->m_allowThread;
@@ -763,11 +551,16 @@ void FunctionModification::setAllowThread(FunctionModification::AllowThread allo
d->m_allowThread = allow;
}
-bool FunctionModification::matches(const QString &functionSignature) const
+bool FunctionModification::matches(const QStringList &functionSignatures) const
{
- return d->m_signature.isEmpty()
- ? d->m_signaturePattern.match(functionSignature).hasMatch()
- : d->m_signature == functionSignature;
+ if (!d->m_signature.isEmpty())
+ return functionSignatures.contains(d->m_signature);
+
+ for (const auto &s : functionSignatures) {
+ if (d->m_signaturePattern.match(s).hasMatch())
+ return true;
+ }
+ return false;
}
bool FunctionModification::setSignature(const QString &s, QString *errorMessage)
@@ -876,37 +669,4 @@ QDebug operator<<(QDebug d, const FunctionModification &fm)
d << ')';
return d;
}
-
-QDebug operator<<(QDebug d, const AddedFunction::Argument &a)
-{
- QDebugStateSaver saver(d);
- d.noquote();
- d.nospace();
- d << "Argument(";
- d << a.typeInfo;
- if (!a.name.isEmpty())
- d << ' ' << a.name;
- if (!a.defaultValue.isEmpty())
- d << " = " << a.defaultValue;
- d << ')';
- return d;
-}
-
-QDebug operator<<(QDebug d, const AddedFunction &af)
-{
- QDebugStateSaver saver(d);
- d.noquote();
- d.nospace();
- d << "AddedFunction(";
- if (af.access() == AddedFunction::Protected)
- d << "protected";
- if (af.isStatic())
- d << " static";
- d << af.returnType() << ' ' << af.name() << '(' << af.arguments() << ')';
- if (af.isConstant())
- d << " const";
- if (af.isDeclaration())
- d << " [declaration]";
- return d;
-}
#endif // !QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h
index 57dc3e2b0..27a38f1aa 100644
--- a/sources/shiboken6/ApiExtractor/modifications.h
+++ b/sources/shiboken6/ApiExtractor/modifications.h
@@ -5,8 +5,7 @@
#define MODIFICATIONS_H
#include "typesystem_enums.h"
-#include "typesystem_typedefs.h"
-#include "parser/typeinfo.h"
+#include "modifications_typedefs.h"
#include <QtCore/QList>
#include <QtCore/QSharedDataPointer>
@@ -65,8 +64,8 @@ public:
explicit ArgumentModification(int idx);
ArgumentModification(const ArgumentModification &);
ArgumentModification &operator=(const ArgumentModification &);
- ArgumentModification(ArgumentModification &&);
- ArgumentModification &operator=(ArgumentModification &&);
+ ArgumentModification(ArgumentModification &&) noexcept;
+ ArgumentModification &operator=(ArgumentModification &&) noexcept;
~ArgumentModification();
// Reference count flags for this argument
@@ -135,15 +134,14 @@ public:
FunctionModification();
FunctionModification(const FunctionModification &);
FunctionModification &operator=(const FunctionModification &);
- FunctionModification(FunctionModification &&);
- FunctionModification &operator=(FunctionModification &&);
+ FunctionModification(FunctionModification &&) noexcept;
+ FunctionModification &operator=(FunctionModification &&) noexcept;
~FunctionModification();
enum ModifierFlag {
Private = 0x0001,
Protected = 0x0002,
- Public = 0x0003,
- Friendly = 0x0004,
+ Public = 0x0004,
AccessModifierMask = 0x000f,
Final = 0x0010,
@@ -156,7 +154,8 @@ public:
CodeInjection = 0x1000,
Rename = 0x2000,
Deprecated = 0x4000,
- ReplaceExpression = 0x8000
+ Undeprecated = 0x8000,
+ ReplaceExpression = 0x10000
};
Q_DECLARE_FLAGS(Modifiers, ModifierFlag);
@@ -191,10 +190,6 @@ public:
{
return accessModifier() == Public;
}
- bool isFriendly() const
- {
- return accessModifier() == Friendly;
- }
bool isFinal() const
{
return modifiers().testFlag(Final);
@@ -203,7 +198,6 @@ public:
{
return modifiers().testFlag(NonFinal);
}
- QString accessModifierString() const;
bool isDeprecated() const
{
@@ -223,13 +217,11 @@ public:
{
return modifiers().testFlag(CodeInjection);
}
- void setIsThread(bool flag);
- bool isThread() const;
AllowThread allowThread() const;
void setAllowThread(AllowThread allow);
- bool matches(const QString &functionSignature) const;
+ bool matches(const QStringList &functionSignatures) const;
bool setSignature(const QString &s, QString *errorMessage = nullptr);
QString signature() const;
@@ -279,8 +271,8 @@ public:
FieldModification();
FieldModification(const FieldModification &);
FieldModification &operator=(const FieldModification &);
- FieldModification(FieldModification &&);
- FieldModification &operator=(FieldModification &&);
+ FieldModification(FieldModification &&) noexcept;
+ FieldModification &operator=(FieldModification &&) noexcept;
~FieldModification();
QString name() const;
@@ -309,121 +301,6 @@ private:
QSharedDataPointer<FieldModificationData> d;
};
-/**
-* \internal
-* Struct used to store information about functions added by the typesystem.
-* This info will be used later to create a fake AbstractMetaFunction which
-* will be inserted into the right AbstractMetaClass.
-*/
-struct AddedFunction
-{
- using AddedFunctionPtr = QSharedPointer<AddedFunction>;
-
- /// Function access types.
- enum Access {
- Protected = 0x1,
- Public = 0x2
- };
-
- struct Argument
- {
- TypeInfo typeInfo;
- QString name;
- QString defaultValue;
- };
-
- /// Creates a new AddedFunction with a signature and a return type.
- explicit AddedFunction(const QString &name, const QList<Argument> &arguments,
- const TypeInfo &returnType);
-
- static AddedFunctionPtr createAddedFunction(const QString &signatureIn,
- const QString &returnTypeIn,
- QString *errorMessage);
-
- AddedFunction() = default;
-
- /// Returns the function name.
- QString name() const
- {
- return m_name;
- }
-
- /// Set the function access type.
- void setAccess(Access access)
- {
- m_access = access;
- }
-
- /// Returns the function access type.
- Access access() const
- {
- return m_access;
- }
-
- /// Returns the function return type.
- TypeInfo returnType() const
- {
- return m_returnType;
- }
-
- /// Returns a list of argument type infos.
- const QList<Argument> &arguments() const
- {
- return m_arguments;
- }
-
- /// Returns true if this is a constant method.
- bool isConstant() const
- {
- return m_isConst;
- }
- void setConstant(bool c) { m_isConst = c; };
-
- /// Set this method static.
- void setStatic(bool value)
- {
- m_isStatic = value;
- }
-
- /// Set this method as a classmethod.
- void setClassMethod(bool value)
- {
- m_isClassMethod = value;
- }
-
- /// Returns true if this is a static method.
- bool isStatic() const
- {
- return m_isStatic;
- }
-
- /// Returns true if this is a class method.
- bool isClassMethod() const
- {
- return m_isClassMethod;
- }
-
- bool isDeclaration() const { return m_isDeclaration; } // <declare-function>
- void setDeclaration(bool value) { m_isDeclaration = value; }
-
- FunctionModificationList modifications;
-
-private:
- QString m_name;
- QList<Argument> m_arguments;
- TypeInfo m_returnType;
- Access m_access = Public;
- bool m_isConst = false;
- bool m_isClassMethod = false;
- bool m_isStatic = false;
- bool m_isDeclaration = false;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const AddedFunction::Argument &a);
-QDebug operator<<(QDebug d, const AddedFunction &af);
-#endif
-
class DocModification
{
public:
diff --git a/sources/shiboken6/ApiExtractor/modifications_typedefs.h b/sources/shiboken6/ApiExtractor/modifications_typedefs.h
new file mode 100644
index 000000000..3b86c55d3
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/modifications_typedefs.h
@@ -0,0 +1,25 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef MODIFICATIONS_TYPEDEFS_H
+#define MODIFICATIONS_TYPEDEFS_H
+
+#include <QtCore/QList>
+
+#include <memory>
+
+class CodeSnip;
+class DocModification;
+
+struct AddedFunction;
+class FieldModification;
+class FunctionModification;
+
+using AddedFunctionPtr = std::shared_ptr<AddedFunction>;
+using AddedFunctionList = QList<AddedFunctionPtr>;
+using CodeSnipList = QList<CodeSnip>;
+using DocModificationList = QList<DocModification>;
+using FieldModificationList = QList<FieldModification>;
+using FunctionModificationList = QList<FunctionModification>;
+
+#endif // MODIFICATIONS_TYPEDEFS_H
diff --git a/sources/shiboken6/ApiExtractor/namespacetypeentry.h b/sources/shiboken6/ApiExtractor/namespacetypeentry.h
index dd0656009..6ffd38430 100644
--- a/sources/shiboken6/ApiExtractor/namespacetypeentry.h
+++ b/sources/shiboken6/ApiExtractor/namespacetypeentry.h
@@ -12,12 +12,12 @@ class NamespaceTypeEntry : public ComplexTypeEntry
{
public:
explicit NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeEntry *clone() const override;
- const NamespaceTypeEntry *extends() const;
- void setExtends(const NamespaceTypeEntry *e);
+ NamespaceTypeEntryCPtr extends() const;
+ void setExtends(const NamespaceTypeEntryCPtr &e);
const QRegularExpression &filePattern() const; // restrict files
void setFilePattern(const QRegularExpression &r);
@@ -33,6 +33,7 @@ public:
bool isInlineNamespace() const;
void setInlineNamespace(bool i);
+ static bool isVisibleScope(const TypeEntryCPtr &e);
static bool isVisibleScope(const TypeEntry *e);
#ifndef QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken6/ApiExtractor/objecttypeentry.h b/sources/shiboken6/ApiExtractor/objecttypeentry.h
index a9df6b4fb..da91e8ff4 100644
--- a/sources/shiboken6/ApiExtractor/objecttypeentry.h
+++ b/sources/shiboken6/ApiExtractor/objecttypeentry.h
@@ -10,7 +10,7 @@ class ObjectTypeEntry : public ComplexTypeEntry
{
public:
explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeEntry *clone() const override;
diff --git a/sources/shiboken6/ApiExtractor/optionsparser.cpp b/sources/shiboken6/ApiExtractor/optionsparser.cpp
new file mode 100644
index 000000000..f2e64c7e4
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/optionsparser.cpp
@@ -0,0 +1,232 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "optionsparser.h"
+#include "messages.h"
+#include "exception.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+
+using namespace Qt::StringLiterals;
+
+template <class Stream> void formatBoolOption(Stream &s, const BoolOption &bo)
+{
+ switch (bo.source) {
+ case OptionSource::CommandLine:
+ s << "--";
+ break;
+ case OptionSource::CommandLineSingleDash:
+ s << '-';
+ break;
+ default:
+ break;
+ }
+ s << bo.option;
+ if (bo.source == OptionSource::ProjectFile)
+ s << " (project)";
+}
+
+template <class Stream> void formatOptionValue(Stream &s, const OptionValue &ov)
+{
+ switch (ov.source) {
+ case OptionSource::CommandLine:
+ s << "--";
+ break;
+ case OptionSource::CommandLineSingleDash:
+ s << '-';
+ break;
+ default:
+ break;
+ }
+ s << ov.option << '=' << ov.value;
+ if (ov.source == OptionSource::ProjectFile)
+ s << " (project)";
+}
+
+QTextStream &operator<<(QTextStream &s, const BoolOption &bo)
+{
+ formatBoolOption(s, bo);
+ return s;
+}
+
+QTextStream &operator<<(QTextStream &s, const OptionValue &ov)
+{
+ formatOptionValue(s, ov);
+ return s;
+}
+
+QDebug operator<<(QDebug debug, const BoolOption &bo)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ formatBoolOption(debug, bo);
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const OptionValue &v)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ formatOptionValue(debug, v);
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const Options &v)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "Options(";
+ if (!v.boolOptions.isEmpty())
+ debug << "bools=" << v.boolOptions;
+ if (!v.valueOptions.isEmpty())
+ debug << ", option values=" << v.valueOptions;
+ if (!v.positionalArguments.isEmpty())
+ debug << ", pos=" << v.positionalArguments;
+ debug << ')';
+ return debug;
+}
+
+QTextStream &operator<<(QTextStream &s, const OptionDescription &od)
+{
+ if (!od.name.startsWith(u'-'))
+ s << "--";
+ s << od.name;
+ if (od.description.isEmpty()) { // For formatting {{"-s", ""}, {"--short", "descr"}}
+ s << ", ";
+ } else {
+ s << '\n';
+ const auto lines = QStringView{od.description}.split(u'\n');
+ for (const auto &line : lines)
+ s << " " << line << '\n';
+ s << '\n';
+ }
+ return s;
+}
+
+QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options)
+{
+ s.setFieldAlignment(QTextStream::AlignLeft);
+ for (const auto &od : options)
+ s << od;
+ return s;
+}
+
+OptionsParser::OptionsParser() noexcept = default;
+OptionsParser::~OptionsParser() = default;
+
+const QString &OptionsParser::pathSyntax()
+{
+ static const QString result =
+ u"<path>["_s + QDir::listSeparator() + u"<path>"_s
+ + QDir::listSeparator() + u"...]"_s;
+ return result;
+}
+
+bool OptionsParser::handleBoolOption(const QString &, OptionSource)
+{
+ return false;
+}
+
+bool OptionsParser::handleOption(const QString &, const QString &, OptionSource)
+{
+ return false;
+}
+
+void OptionsParser::process(Options *o)
+{
+ for (auto i = o->boolOptions.size() - 1; i >= 0; --i) {
+ const auto &opt = o->boolOptions.at(i);
+ if (handleBoolOption(opt.option, opt.source))
+ o->boolOptions.removeAt(i);
+ }
+ for (auto i = o->valueOptions.size() - 1; i >= 0; --i) {
+ const auto &opt = o->valueOptions.at(i);
+ if (handleOption(opt.option, opt.value, opt.source))
+ o->valueOptions.removeAt(i);
+ }
+}
+
+bool OptionsParserList::handleBoolOption(const QString &key, OptionSource source)
+{
+ for (const auto &p : std::as_const(m_parsers)) {
+ if (p->handleBoolOption(key, source))
+ return true;
+ }
+ return false;
+}
+
+bool OptionsParserList::handleOption(const QString &key, const QString &value, OptionSource source)
+{
+ for (const auto &p : std::as_const(m_parsers)) {
+ if (p->handleOption(key, value, source))
+ return true;
+ }
+ return false;
+}
+
+static void processOption(const QString &o, OptionSource source,
+ BoolOptions *bools, OptionValues *values)
+{
+ const auto equals = o.indexOf(u'=');
+ if (equals == -1) {
+ bools->append({o.trimmed(), source});
+ } else {
+ QString key = o.left(equals).trimmed();
+ QString value = o.mid(equals + 1).trimmed();
+ if (!value.isEmpty())
+ values->append({key, value, source});
+ }
+}
+
+static void readProjectFile(const QString &name, Options *o)
+{
+ const auto startMarker = "[generator-project]"_ba;
+
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ throw Exception(msgCannotOpenForReading(file));
+
+ if (file.atEnd() || file.readLine().trimmed() != startMarker)
+ throw Exception(msgMissingProjectFileMarker(name, startMarker));
+
+ while (!file.atEnd()) {
+ const QByteArray lineB = file.readLine().trimmed();
+ if (!lineB.isEmpty() && !lineB.startsWith('#')) {
+ processOption(QString::fromUtf8(lineB), OptionSource::ProjectFile,
+ &o->boolOptions, &o->valueOptions);
+ }
+ }
+}
+
+void Options::setOptions(const QStringList &argv)
+{
+ const auto projectFileOption = "--project-file="_L1;
+ for (const auto &o : argv) {
+ if (o.startsWith(projectFileOption)) {
+ readProjectFile(o.sliced(projectFileOption.size()), this);
+ } else if (o.startsWith(u"--")) {
+ processOption(o.sliced(2), OptionSource::CommandLine,
+ &boolOptions, &valueOptions);
+ } else if (o.startsWith(u'-')) {
+ processOption(o.sliced(1), OptionSource::CommandLineSingleDash,
+ &boolOptions, &valueOptions);
+ } else {
+ positionalArguments.append(o);
+ }
+ }
+}
+
+QString Options::msgUnprocessedOptions() const
+{
+ QString result;
+ QTextStream str(&result);
+ for (const auto &b : boolOptions)
+ str << b << ' ';
+ for (const auto &v : valueOptions)
+ str << v << ' ';
+ return result.trimmed();
+}
diff --git a/sources/shiboken6/ApiExtractor/optionsparser.h b/sources/shiboken6/ApiExtractor/optionsparser.h
new file mode 100644
index 000000000..d5557dc15
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/optionsparser.h
@@ -0,0 +1,98 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef OPTIONSPARSER_H
+#define OPTIONSPARSER_H
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include <memory>
+
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+enum class OptionSource
+{
+ CommandLine, // "--option"
+ CommandLineSingleDash, // "-o"
+ ProjectFile
+};
+
+struct BoolOption
+{
+ QString option;
+ OptionSource source = OptionSource::CommandLine;
+};
+
+struct OptionValue // --option=value pair
+{
+ QString option;
+ QString value;
+ OptionSource source = OptionSource::CommandLine;
+};
+
+using BoolOptions = QList<BoolOption>;
+using OptionValues = QList<OptionValue>;
+
+struct Options // Options from command line and project file
+{
+ void setOptions(const QStringList &argv);
+ QString msgUnprocessedOptions() const;
+
+ BoolOptions boolOptions;
+ OptionValues valueOptions;
+ QStringList positionalArguments;
+};
+
+struct OptionDescription // For help formatting
+{
+ QString name;
+ QString description;
+};
+
+using OptionDescriptions = QList<OptionDescription>;
+
+QTextStream &operator<<(QTextStream &s, const BoolOption &bo);
+QTextStream &operator<<(QTextStream &s, const OptionValue &ov);
+QTextStream &operator<<(QTextStream &s, const OptionDescription &od);
+QTextStream &operator<<(QTextStream &s, const OptionDescriptions &options);
+
+class OptionsParser
+{
+public:
+ Q_DISABLE_COPY_MOVE(OptionsParser)
+
+ virtual ~OptionsParser();
+
+ // Return true to indicate the option was processed.
+ virtual bool handleBoolOption(const QString &key, OptionSource source);
+ virtual bool handleOption(const QString &key, const QString &value, OptionSource source);
+
+ void process(Options *);
+
+ static const QString &pathSyntax();
+
+protected:
+ OptionsParser() noexcept;
+};
+
+class OptionsParserList : public OptionsParser
+{
+public:
+ using OptionsParserPtr = std::shared_ptr<OptionsParser>;
+
+ void append(const OptionsParserPtr &parser) { m_parsers.append(parser); }
+ void clear() { m_parsers.clear(); }
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value, OptionSource source) override;
+
+private:
+ QList<OptionsParserPtr> m_parsers;
+};
+
+QDebug operator<<(QDebug debug, const BoolOption &bo);
+QDebug operator<<(QDebug debug, const OptionValue &v);
+QDebug operator<<(QDebug debug, const Options &v);
+
+#endif // OPTIONSPARSER_H
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
index 4099caa2c..259a706dc 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
@@ -6,31 +6,24 @@
#include "codemodel.h"
#include <sourcelocation.h>
+#include <debughelpers_p.h>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QRegularExpression>
#include <algorithm>
-#include <functional>
-#include <iostream>
-// Predicate to find an item by name in a list of QSharedPointer<Item>
-template <class T> class ModelItemNamePredicate
-{
-public:
- explicit ModelItemNamePredicate(const QString &name) : m_name(name) {}
- bool operator()(const QSharedPointer<T> &item) const { return item->name() == m_name; }
-
-private:
- const QString m_name;
-};
+using namespace Qt::StringLiterals;
template <class T>
-static QSharedPointer<T> findModelItem(const QList<QSharedPointer<T> > &list, const QString &name)
+static std::shared_ptr<T> findModelItem(const QList<std::shared_ptr<T> > &list,
+ QAnyStringView name)
{
- const auto it = std::find_if(list.cbegin(), list.cend(), ModelItemNamePredicate<T>(name));
- return it != list.cend() ? *it : QSharedPointer<T>();
+ using ItemPtr = std::shared_ptr<T>;
+ auto pred = [name](const ItemPtr &item) { return item->name() == name; };
+ const auto it = std::find_if(list.cbegin(), list.cend(), pred);
+ return it != list.cend() ? *it : ItemPtr{};
}
// ---------------------------------------------------------------------------
@@ -51,7 +44,7 @@ void CodeModel::addFile(const FileModelItem &item)
m_files.append(item);
}
-FileModelItem CodeModel::findFile(const QString &name) const
+FileModelItem CodeModel::findFile(QAnyStringView name) const
{
return findModelItem(m_files, name);
}
@@ -69,11 +62,11 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope,
return tp;
if (TemplateTypeAliasModelItem tta = scope->findTemplateTypeAlias(nameSegment))
return tta;
- return CodeModelItem();
+ return {};
}
if (auto nestedClass = scope->findClass(nameSegment))
return findRecursion(nestedClass, qualifiedName, segment + 1);
- if (auto namespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) {
+ if (auto namespaceItem = std::dynamic_pointer_cast<_NamespaceModelItem>(scope)) {
for (const auto &nestedNamespace : namespaceItem->namespaces()) {
if (nestedNamespace->name() == nameSegment) {
if (auto item = findRecursion(nestedNamespace, qualifiedName, segment + 1))
@@ -81,7 +74,7 @@ static CodeModelItem findRecursion(const ScopeModelItem &scope,
}
}
}
- return CodeModelItem();
+ return {};
}
CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, const ScopeModelItem &scope)
@@ -118,7 +111,7 @@ QDebug operator<<(QDebug d, const CodeModel *m)
d << "CodeModel(";
if (m) {
const NamespaceModelItem globalNamespaceP = m->globalNamespace();
- if (globalNamespaceP.data())
+ if (globalNamespaceP)
globalNamespaceP->formatDebug(d);
} else {
d << '0';
@@ -241,27 +234,17 @@ void _CodeModelItem::setEnclosingScope(const _ScopeModelItem *s)
m_enclosingScope = s;
}
-#ifndef QT_NO_DEBUG_STREAM
-template <class It>
-void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ")
+_ScopeModelItem::_ScopeModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
{
- for (It i = i1; i != i2; ++i) {
- if (i != i1)
- d << separator;
- d << *i;
- }
}
-template <class It>
-static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ")
+_ScopeModelItem::_ScopeModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
{
- for (It i = i1; i != i2; ++i) {
- if (i != i1)
- d << separator;
- d << i->data();
- }
}
+#ifndef QT_NO_DEBUG_STREAM
void _CodeModelItem::formatKind(QDebug &d, int k)
{
switch (k) {
@@ -371,6 +354,16 @@ bool _ClassModelItem::extendsClass(const QString &name) const
return false;
}
+_ClassModelItem::_ClassModelItem(CodeModel *model, int kind)
+ : _ScopeModelItem(model, kind)
+{
+}
+
+_ClassModelItem::_ClassModelItem(CodeModel *model, const QString &name, int kind)
+ : _ScopeModelItem(model, name, kind)
+{
+}
+
const QList<_ClassModelItem::UsingMember> &_ClassModelItem::usingMembers() const
{
return m_usingMembers;
@@ -413,9 +406,9 @@ template <class List>
static void formatModelItemList(QDebug &d, const char *prefix, const List &l,
const char *separator = ", ")
{
- if (const int size = l.size()) {
+ if (const auto size = l.size()) {
d << prefix << '[' << size << "](";
- for (int i = 0; i < size; ++i) {
+ for (qsizetype i = 0; i < size; ++i) {
if (i)
d << separator;
l.at(i)->formatDebug(d);
@@ -432,7 +425,7 @@ void _ClassModelItem::formatDebug(QDebug &d) const
d << " [final]";
d << ", inherits=";
d << ", inherits=";
- for (int i = 0, size = m_baseClasses.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = m_baseClasses.size(); i < size; ++i) {
if (i)
d << ", ";
d << m_baseClasses.at(i).name << " (" << m_baseClasses.at(i).accessPolicy << ')';
@@ -451,12 +444,12 @@ void _ClassModelItem::formatDebug(QDebug &d) const
// ---------------------------------------------------------------------------
FunctionModelItem _ScopeModelItem::declaredFunction(const FunctionModelItem &item)
{
- for (const FunctionModelItem &fun : qAsConst(m_functions)) {
+ for (const FunctionModelItem &fun : std::as_const(m_functions)) {
if (fun->name() == item->name() && fun->isSimilar(item))
return fun;
}
- return FunctionModelItem();
+ return {};
}
_ScopeModelItem::~_ScopeModelItem() = default;
@@ -556,7 +549,7 @@ template class LIBSAMPLE_EXPORT Tpl<54>;
*/
void _ScopeModelItem::purgeClassDeclarations()
{
- for (int i = m_classes.size() - 1; i >= 0; --i) {
+ for (auto i = m_classes.size() - 1; i >= 0; --i) {
auto klass = m_classes.at(i);
// For an empty class, check if there is a matching template
// definition, and remove it if this is the case.
@@ -625,52 +618,46 @@ void _ScopeModelItem::formatDebug(QDebug &d) const
}
#endif // !QT_NO_DEBUG_STREAM
-namespace {
// Predicate to match a non-template class name against the class list.
// "Vector" should match "Vector" as well as "Vector<T>" (as seen for methods
// from within the class "Vector").
-class ClassNamePredicate
+static bool matchClassNameNonTemplatePart(const ClassModelItem &item, const QString &name)
{
-public:
- explicit ClassNamePredicate(const QString &name) : m_name(name) {}
- bool operator()(const ClassModelItem &item) const
- {
- const QString &itemName = item->name();
- if (!itemName.startsWith(m_name))
- return false;
- return itemName.size() == m_name.size() || itemName.at(m_name.size()) == u'<';
- }
-
-private:
- const QString m_name;
-};
-} // namespace
+ const QString &itemName = item->name();
+ if (!itemName.startsWith(name))
+ return false;
+ return itemName.size() == name.size() || itemName.at(name.size()) == u'<';
+}
ClassModelItem _ScopeModelItem::findClass(const QString &name) const
{
// A fully qualified template is matched by name only
const ClassList::const_iterator it = name.contains(u'<')
- ? std::find_if(m_classes.begin(), m_classes.end(), ModelItemNamePredicate<_ClassModelItem>(name))
- : std::find_if(m_classes.begin(), m_classes.end(), ClassNamePredicate(name));
+ ? std::find_if(m_classes.begin(), m_classes.end(),
+ [&name](const ClassModelItem &item) {
+ return item->name() == name; })
+ : std::find_if(m_classes.begin(), m_classes.end(),
+ [&name](const ClassModelItem &item) {
+ return matchClassNameNonTemplatePart(item, name); });
return it != m_classes.end() ? *it : ClassModelItem();
}
-VariableModelItem _ScopeModelItem::findVariable(const QString &name) const
+VariableModelItem _ScopeModelItem::findVariable(QAnyStringView name) const
{
return findModelItem(m_variables, name);
}
-TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const
+TypeDefModelItem _ScopeModelItem::findTypeDef(QAnyStringView name) const
{
return findModelItem(m_typeDefs, name);
}
-TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(const QString &name) const
+TemplateTypeAliasModelItem _ScopeModelItem::findTemplateTypeAlias(QAnyStringView name) const
{
return findModelItem(m_templateTypeAliases, name);
}
-EnumModelItem _ScopeModelItem::findEnum(const QString &name) const
+EnumModelItem _ScopeModelItem::findEnum(QAnyStringView name) const
{
return findModelItem(m_enums, name);
}
@@ -682,15 +669,15 @@ _ScopeModelItem::FindEnumByValueReturn
const bool unqualified = fullValue.size() == enumValue.size();
QString scopePrefix = scope().join(u"::");
if (!scopePrefix.isEmpty())
- scopePrefix += u"::"_qs;
- scopePrefix += name() + u"::"_qs;
+ scopePrefix += u"::"_s;
+ scopePrefix += name() + u"::"_s;
for (const auto &e : m_enums) {
const auto index = e->indexOfValue(enumValue);
if (index != -1) {
QString fullyQualifiedName = scopePrefix;
if (e->enumKind() != AnonymousEnum)
- fullyQualifiedName += e->name() + u"::"_qs;
+ fullyQualifiedName += e->name() + u"::"_s;
fullyQualifiedName += e->enumerators().at(index)->name();
if (unqualified || fullyQualifiedName.endsWith(fullValue))
return {e, fullyQualifiedName};
@@ -722,8 +709,8 @@ _ScopeModelItem::FindEnumByValueReturn
if (searchSiblingNamespaces && scope->kind() == Kind_Namespace) {
if (auto *enclosingNamespace = dynamic_cast<const _NamespaceModelItem *>(enclosingScope)) {
for (const auto &sibling : enclosingNamespace->namespaces()) {
- if (sibling.data() != scope && sibling->name() == scope->name()) {
- if (const auto e = findEnumByValueRecursion(sibling.data(),
+ if (sibling.get() != scope && sibling->name() == scope->name()) {
+ if (const auto e = findEnumByValueRecursion(sibling.get(),
fullValue, enumValue, false)) {
return e;
}
@@ -739,8 +726,8 @@ _ScopeModelItem::FindEnumByValueReturn
// PYSIDE-331: We need to also search the base classes.
if (auto *classItem = dynamic_cast<const _ClassModelItem *>(scope)) {
for (const auto &base : classItem->baseClasses()) {
- if (!base.klass.isNull()) {
- auto *c = base.klass.data();
+ if (base.klass) {
+ auto *c = base.klass.get();
if (const auto e = findEnumByValueRecursion(c, fullValue, enumValue))
return e;
}
@@ -759,7 +746,7 @@ _ScopeModelItem::FindEnumByValueReturn
return findEnumByValueRecursion(this, value, enumValue);
}
-FunctionList _ScopeModelItem::findFunctions(const QString &name) const
+FunctionList _ScopeModelItem::findFunctions(QAnyStringView name) const
{
FunctionList result;
for (const FunctionModelItem &func : m_functions) {
@@ -770,17 +757,25 @@ FunctionList _ScopeModelItem::findFunctions(const QString &name) const
}
// ---------------------------------------------------------------------------
-_NamespaceModelItem::~_NamespaceModelItem()
+_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, int kind)
+ : _ScopeModelItem(model, kind)
{
}
+_NamespaceModelItem::_NamespaceModelItem(CodeModel *model, const QString &name, int kind)
+ : _ScopeModelItem(model, name, kind)
+{
+}
+
+_NamespaceModelItem::~_NamespaceModelItem() = default;
+
void _NamespaceModelItem::addNamespace(NamespaceModelItem item)
{
item->setEnclosingScope(this);
m_namespaces.append(item);
}
-NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const
+NamespaceModelItem _NamespaceModelItem::findNamespace(QAnyStringView name) const
{
return findModelItem(m_namespaces, name);
}
@@ -812,10 +807,18 @@ void _NamespaceModelItem::formatDebug(QDebug &d) const
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
-_ArgumentModelItem::~_ArgumentModelItem()
+_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
{
}
+_ArgumentModelItem::_ArgumentModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
+{
+}
+
+_ArgumentModelItem::~_ArgumentModelItem() = default;
+
TypeInfo _ArgumentModelItem::type() const
{
return m_type;
@@ -836,11 +839,23 @@ void _ArgumentModelItem::setDefaultValue(bool defaultValue)
m_defaultValue = defaultValue;
}
+bool _ArgumentModelItem::scopeResolution() const
+{
+ return m_scopeResolution;
+}
+
+void _ArgumentModelItem::setScopeResolution(bool v)
+{
+ m_scopeResolution = v;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _ArgumentModelItem::formatDebug(QDebug &d) const
{
_CodeModelItem::formatDebug(d);
d << ", type=" << m_type;
+ if (m_scopeResolution)
+ d << ", [m_scope resolution]";
if (m_defaultValue)
d << ", defaultValue=\"" << m_defaultValueExpression << '"';
}
@@ -875,6 +890,16 @@ bool _FunctionModelItem::isSimilar(const FunctionModelItem &other) const
return true;
}
+_FunctionModelItem::_FunctionModelItem(CodeModel *model, int kind)
+ : _MemberModelItem(model, kind), m_flags(0)
+{
+}
+
+_FunctionModelItem::_FunctionModelItem(CodeModel *model, const QString &name, int kind)
+ : _MemberModelItem(model, name, kind), m_flags(0)
+{
+}
+
ArgumentList _FunctionModelItem::arguments() const
{
return m_arguments;
@@ -905,6 +930,16 @@ void _FunctionModelItem::setVariadics(bool isVariadics)
m_isVariadics = isVariadics;
}
+bool _FunctionModelItem::scopeResolution() const
+{
+ return m_scopeResolution;
+}
+
+void _FunctionModelItem::setScopeResolution(bool v)
+{
+ m_scopeResolution = v;
+}
+
bool _FunctionModelItem::isDefaultConstructor() const
{
return m_functionType == CodeModel::Constructor
@@ -967,66 +1002,16 @@ void _FunctionModelItem::setDeleted(bool d)
m_isDeleted = d;
}
-bool _FunctionModelItem::isDeprecated() const
-{
- return m_isDeprecated;
-}
-
-void _FunctionModelItem::setDeprecated(bool d)
-{
- m_isDeprecated = d;
-}
-
-bool _FunctionModelItem::isVirtual() const
-{
- return m_isVirtual;
-}
-
-void _FunctionModelItem::setVirtual(bool isVirtual)
-{
- m_isVirtual = isVirtual;
-}
-
bool _FunctionModelItem::isInline() const
{
return m_isInline;
}
-bool _FunctionModelItem::isOverride() const
-{
- return m_isOverride;
-}
-
-void _FunctionModelItem::setOverride(bool o)
-{
- m_isOverride = o;
-}
-
-bool _FunctionModelItem::isFinal() const
-{
- return m_isFinal;
-}
-
-void _FunctionModelItem::setFinal(bool f)
-{
- m_isFinal = f;
-}
-
void _FunctionModelItem::setInline(bool isInline)
{
m_isInline = isInline;
}
-bool _FunctionModelItem::isExplicit() const
-{
- return m_isExplicit;
-}
-
-void _FunctionModelItem::setExplicit(bool isExplicit)
-{
- m_isExplicit = isExplicit;
-}
-
bool _FunctionModelItem::isHiddenFriend() const
{
return m_isHiddenFriend;
@@ -1037,33 +1022,12 @@ void _FunctionModelItem::setHiddenFriend(bool f)
m_isHiddenFriend = f;
}
-bool _FunctionModelItem::isAbstract() const
-{
- return m_isAbstract;
-}
-
-void _FunctionModelItem::setAbstract(bool isAbstract)
-{
- m_isAbstract = isAbstract;
-}
-
-// Qt
-bool _FunctionModelItem::isInvokable() const
-{
- return m_isInvokable;
-}
-
-void _FunctionModelItem::setInvokable(bool isInvokable)
-{
- m_isInvokable = isInvokable;
-}
-
QString _FunctionModelItem::typeSystemSignature() const // For dumping out type system files
{
QString result;
QTextStream str(&result);
str << name() << '(';
- for (int a = 0, size = m_arguments.size(); a < size; ++a) {
+ for (qsizetype a = 0, size = m_arguments.size(); a < size; ++a) {
if (a)
str << ',';
m_arguments.at(a)->type().formatTypeSystemSignature(str);
@@ -1182,20 +1146,22 @@ void _FunctionModelItem::formatDebug(QDebug &d) const
d << " [deleted!]";
if (m_isInline)
d << " [inline]";
- if (m_isVirtual)
+ if (m_attributes.testFlag(FunctionAttribute::Virtual))
d << " [virtual]";
- if (m_isOverride)
+ if (m_attributes.testFlag(FunctionAttribute::Override))
d << " [override]";
- if (m_isDeprecated)
+ if (m_attributes.testFlag(FunctionAttribute::Deprecated))
d << " [deprecated]";
- if (m_isFinal)
+ if (m_attributes.testFlag(FunctionAttribute::Final))
d << " [final]";
- if (m_isAbstract)
+ if (m_attributes.testFlag(FunctionAttribute::Abstract))
d << " [abstract]";
- if (m_isExplicit)
+ if (m_attributes.testFlag(FunctionAttribute::Explicit))
d << " [explicit]";
if (m_isInvokable)
d << " [invokable]";
+ if (m_scopeResolution)
+ d << " [scope resolution]";
formatModelItemList(d, ", arguments=", m_arguments);
if (m_isVariadics)
d << ",...";
@@ -1203,6 +1169,16 @@ void _FunctionModelItem::formatDebug(QDebug &d) const
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
+_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
+{
+}
+
+_TypeDefModelItem::_TypeDefModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
+{
+}
+
TypeInfo _TypeDefModelItem::type() const
{
return m_type;
@@ -1254,7 +1230,7 @@ void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const
{
_CodeModelItem::formatDebug(d);
d << ", <";
- for (int i = 0, count = m_templateParameters.size(); i < count; ++i) {
+ for (qsizetype i = 0, count = m_templateParameters.size(); i < count; ++i) {
if (i)
d << ", ";
d << m_templateParameters.at(i)->name();
@@ -1264,6 +1240,16 @@ void _TemplateTypeAliasModelItem::formatDebug(QDebug &d) const
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
+_EnumModelItem::_EnumModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
+{
+}
+
+_EnumModelItem::_EnumModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
+{
+}
+
Access _EnumModelItem::accessPolicy() const
{
return m_accessPolicy;
@@ -1305,6 +1291,26 @@ void _EnumModelItem::setSigned(bool s)
m_signed = s;
}
+QString _EnumModelItem::underlyingType() const
+{
+ return m_underlyingType;
+}
+
+void _EnumModelItem::setUnderlyingType(const QString &underlyingType)
+{
+ m_underlyingType = underlyingType;
+}
+
+bool _EnumModelItem::isDeprecated() const
+{
+ return m_deprecated;
+}
+
+void _EnumModelItem::setDeprecated(bool d)
+{
+ m_deprecated = d;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _EnumModelItem::formatDebug(QDebug &d) const
{
@@ -1319,6 +1325,8 @@ void _EnumModelItem::formatDebug(QDebug &d) const
d << " (class)";
break;
}
+ if (m_deprecated)
+ d << " (deprecated)";
if (!m_signed)
d << " (unsigned)";
formatModelItemList(d, ", enumerators=", m_enumerators);
@@ -1328,6 +1336,16 @@ void _EnumModelItem::formatDebug(QDebug &d) const
// ---------------------------------------------------------------------------
_EnumeratorModelItem::~_EnumeratorModelItem() = default;
+_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
+{
+}
+
+_EnumeratorModelItem::_EnumeratorModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
+{
+}
+
QString _EnumeratorModelItem::stringValue() const
{
return m_stringValue;
@@ -1338,17 +1356,40 @@ void _EnumeratorModelItem::setStringValue(const QString &value)
m_stringValue = value;
}
+bool _EnumeratorModelItem::isDeprecated() const
+{
+ return m_deprecated;
+}
+
+void _EnumeratorModelItem::setDeprecated(bool d)
+{
+ m_deprecated = d;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _EnumeratorModelItem::formatDebug(QDebug &d) const
{
_CodeModelItem::formatDebug(d);
d << ", value=" << m_value << ", stringValue=\"" << m_stringValue << '"';
+ if (m_deprecated)
+ d << " (deprecated)";
}
#endif // !QT_NO_DEBUG_STREAM
// ---------------------------------------------------------------------------
_TemplateParameterModelItem::~_TemplateParameterModelItem() = default;
+_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind)
+{
+}
+
+_TemplateParameterModelItem::_TemplateParameterModelItem(CodeModel *model,
+ const QString &name, int kind)
+ : _CodeModelItem(model, name, kind)
+{
+}
+
TypeInfo _TemplateParameterModelItem::type() const
{
return m_type;
@@ -1412,6 +1453,16 @@ void _MemberModelItem::setStatic(bool isStatic)
m_isStatic = isStatic;
}
+_MemberModelItem::_MemberModelItem(CodeModel *model, int kind)
+ : _CodeModelItem(model, kind), m_flags(0)
+{
+}
+
+_MemberModelItem::_MemberModelItem(CodeModel *model, const QString &name, int kind)
+ : _CodeModelItem(model, name, kind), m_flags(0)
+{
+}
+
bool _MemberModelItem::isConstant() const
{
return m_isConstant;
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h
index 58c7a9d2c..b31c09163 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h
@@ -12,7 +12,6 @@
#include "typeinfo.h"
#include <QtCore/QHash>
-#include <QtCore/QPair>
#include <QtCore/QSet>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -20,6 +19,7 @@
#include <QtCore/QWeakPointer>
#include <optional>
+#include <utility>
QT_FORWARD_DECLARE_CLASS(QDebug)
@@ -32,7 +32,7 @@ class CodeModel
{
Q_GADGET
public:
- Q_DISABLE_COPY(CodeModel)
+ Q_DISABLE_COPY_MOVE(CodeModel)
enum FunctionType {
Normal,
@@ -74,7 +74,7 @@ public:
NamespaceModelItem globalNamespace() const;
void addFile(const FileModelItem &item);
- FileModelItem findFile(const QString &name) const;
+ FileModelItem findFile(QAnyStringView name) const;
static CodeModelItem findItem(const QStringList &qualifiedName,
const ScopeModelItem &scope);
@@ -91,8 +91,9 @@ QDebug operator<<(QDebug d, const CodeModel *m);
class _CodeModelItem
{
- Q_DISABLE_COPY(_CodeModelItem)
public:
+ Q_DISABLE_COPY_MOVE(_CodeModelItem)
+
enum Kind {
/* These are bit-flags resembling inheritance */
Kind_Scope = 0x1,
@@ -175,6 +176,7 @@ QDebug operator<<(QDebug d, const _CodeModelItem *t);
class _ScopeModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_ScopeModelItem)
DECLARE_MODEL_NODE(Scope)
~_ScopeModelItem();
@@ -194,21 +196,21 @@ public:
void addVariable(const VariableModelItem &item);
ClassModelItem findClass(const QString &name) const;
- EnumModelItem findEnum(const QString &name) const;
+ EnumModelItem findEnum(QAnyStringView name) const;
struct FindEnumByValueReturn
{
- operator bool() const { return !item.isNull(); }
+ operator bool() const { return bool(item); }
EnumModelItem item;
QString qualifiedName;
};
FindEnumByValueReturn findEnumByValue(QStringView value) const;
- FunctionList findFunctions(const QString &name) const;
- TypeDefModelItem findTypeDef(const QString &name) const;
- TemplateTypeAliasModelItem findTemplateTypeAlias(const QString &name) const;
- VariableModelItem findVariable(const QString &name) const;
+ FunctionList findFunctions(QAnyStringView name) const;
+ TypeDefModelItem findTypeDef(QAnyStringView name) const;
+ TemplateTypeAliasModelItem findTemplateTypeAlias(QAnyStringView name) const;
+ VariableModelItem findVariable(QAnyStringView name) const;
void addEnumsDeclaration(const QString &enumsDeclaration);
QStringList enumsDeclarations() const { return m_enumsDeclarations; }
@@ -223,10 +225,9 @@ public:
#endif
protected:
- explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind) {}
- explicit _ScopeModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind) {}
+ explicit _ScopeModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _ScopeModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
void appendScope(const _ScopeModelItem &other);
@@ -258,6 +259,7 @@ private:
class _ClassModelItem: public _ScopeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_ClassModelItem)
DECLARE_MODEL_NODE(Class)
struct BaseClass
@@ -274,10 +276,9 @@ public:
Access access = Access::Public;
};
- explicit _ClassModelItem(CodeModel *model, int kind = __node_kind)
- : _ScopeModelItem(model, kind), m_classType(CodeModel::Class) {}
- explicit _ClassModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {}
+ explicit _ClassModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _ClassModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_ClassModelItem();
const QList<BaseClass> &baseClasses() const { return m_baseClasses; }
@@ -313,7 +314,7 @@ private:
QList<BaseClass> m_baseClasses;
QList<UsingMember> m_usingMembers;
TemplateParameterList m_templateParameters;
- CodeModel::ClassType m_classType;
+ CodeModel::ClassType m_classType = CodeModel::Class;
QStringList m_propertyDeclarations;
bool m_final = false;
@@ -322,12 +323,12 @@ private:
class _NamespaceModelItem: public _ScopeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_NamespaceModelItem)
DECLARE_MODEL_NODE(Namespace)
- explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind)
- : _ScopeModelItem(model, kind) {}
- explicit _NamespaceModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _ScopeModelItem(model, name, kind) {}
+ explicit _NamespaceModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _NamespaceModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_NamespaceModelItem();
const NamespaceList &namespaces() const { return m_namespaces; }
@@ -337,7 +338,7 @@ public:
void addNamespace(NamespaceModelItem item);
- NamespaceModelItem findNamespace(const QString &name) const;
+ NamespaceModelItem findNamespace(QAnyStringView name) const;
void appendNamespace(const _NamespaceModelItem &other);
@@ -353,24 +354,23 @@ private:
class _FileModelItem: public _NamespaceModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_FileModelItem)
DECLARE_MODEL_NODE(File)
- explicit _FileModelItem(CodeModel *model, int kind = __node_kind)
- : _NamespaceModelItem(model, kind) {}
- explicit _FileModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _NamespaceModelItem(model, name, kind) {}
+ using _NamespaceModelItem::_NamespaceModelItem;
+
~_FileModelItem();
};
class _ArgumentModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_ArgumentModelItem)
DECLARE_MODEL_NODE(Argument)
- explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind), m_defaultValue(false) {}
- explicit _ArgumentModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind), m_defaultValue(false) {}
+ explicit _ArgumentModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _ArgumentModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_ArgumentModelItem();
TypeInfo type() const;
@@ -382,6 +382,10 @@ public:
QString defaultValueExpression() const { return m_defaultValueExpression; }
void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; }
+ // Argument type has scope resolution "::ArgumentType"
+ bool scopeResolution() const;
+ void setScopeResolution(bool v);
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
@@ -389,18 +393,19 @@ public:
private:
TypeInfo m_type;
QString m_defaultValueExpression;
- bool m_defaultValue;
+ bool m_defaultValue = false;
+ bool m_scopeResolution = false;
};
class _MemberModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_MemberModelItem)
DECLARE_MODEL_NODE(Member)
- explicit _MemberModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind), m_accessPolicy(Access::Public), m_flags(0) {}
- explicit _MemberModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind), m_accessPolicy(Access::Public), m_flags(0) {}
+ explicit _MemberModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _MemberModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_MemberModelItem();
bool isConstant() const;
@@ -443,7 +448,7 @@ public:
private:
TemplateParameterList m_templateParameters;
TypeInfo m_type;
- Access m_accessPolicy;
+ Access m_accessPolicy = Access::Public;
union {
struct {
uint m_isConstant: 1;
@@ -463,12 +468,12 @@ private:
class _FunctionModelItem: public _MemberModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_FunctionModelItem)
DECLARE_MODEL_NODE(Function)
- explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind)
- : _MemberModelItem(model, kind), m_functionType(CodeModel::Normal), m_flags(0) {}
- explicit _FunctionModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _MemberModelItem(model, name, kind), m_functionType(CodeModel::Normal), m_flags(0) {}
+ explicit _FunctionModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _FunctionModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_FunctionModelItem();
ArgumentList arguments() const;
@@ -480,39 +485,25 @@ public:
static std::optional<CodeModel::FunctionType> functionTypeFromName(QStringView name);
+ FunctionAttributes attributes() const { return m_attributes; }
+ void setAttributes(FunctionAttributes a) { m_attributes = a; }
+ void setAttribute(FunctionAttribute a, bool on = true) { m_attributes.setFlag(a, on); }
+
bool isDeleted() const;
void setDeleted(bool d);
- bool isDeprecated() const;
- void setDeprecated(bool d);
-
- bool isVirtual() const;
- void setVirtual(bool isVirtual);
-
- bool isOverride() const;
- void setOverride(bool o);
-
- bool isFinal() const;
- void setFinal(bool f);
-
bool isInline() const;
void setInline(bool isInline);
- bool isExplicit() const;
- void setExplicit(bool isExplicit);
-
bool isHiddenFriend() const;
void setHiddenFriend(bool f);
- bool isInvokable() const; // Qt
- void setInvokable(bool isInvokable); // Qt
-
- bool isAbstract() const;
- void setAbstract(bool isAbstract);
-
bool isVariadics() const;
void setVariadics(bool isVariadics);
+ bool scopeResolution() const; // Return type has scope resolution "::ReturnType"
+ void setScopeResolution(bool v);
+
bool isDefaultConstructor() const;
bool isSpaceshipOperator() const;
@@ -538,20 +529,16 @@ private:
CodeModel::FunctionType _determineTypeHelper() const;
ArgumentList m_arguments;
- CodeModel::FunctionType m_functionType;
+ FunctionAttributes m_attributes;
+ CodeModel::FunctionType m_functionType = CodeModel::Normal;
union {
struct {
uint m_isDeleted: 1;
- uint m_isVirtual: 1;
- uint m_isOverride: 1;
- uint m_isFinal: 1;
- uint m_isDeprecated: 1;
uint m_isInline: 1;
- uint m_isAbstract: 1;
- uint m_isExplicit: 1;
uint m_isVariadics: 1;
uint m_isHiddenFriend: 1;
uint m_isInvokable : 1; // Qt
+ uint m_scopeResolution: 1;
};
uint m_flags;
};
@@ -563,10 +550,7 @@ class _VariableModelItem: public _MemberModelItem
public:
DECLARE_MODEL_NODE(Variable)
- explicit _VariableModelItem(CodeModel *model, int kind = __node_kind)
- : _MemberModelItem(model, kind) {}
- explicit _VariableModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _MemberModelItem(model, name, kind) {}
+ using _MemberModelItem::_MemberModelItem;
};
class _TypeDefModelItem: public _CodeModelItem
@@ -574,10 +558,9 @@ class _TypeDefModelItem: public _CodeModelItem
public:
DECLARE_MODEL_NODE(TypeDef)
- explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind) {}
- explicit _TypeDefModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind) {}
+ explicit _TypeDefModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _TypeDefModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
TypeInfo type() const;
void setType(const TypeInfo &type);
@@ -617,12 +600,11 @@ private:
class _EnumModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_EnumModelItem)
DECLARE_MODEL_NODE(Enum)
- explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind) {}
- explicit _EnumModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind) {}
+ explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind);
+ explicit _EnumModelItem(CodeModel *model, int kind = __node_kind);
~_EnumModelItem();
Access accessPolicy() const;
@@ -641,25 +623,33 @@ public:
void formatDebug(QDebug &d) const override;
#endif
+ bool isDeprecated() const;
+ void setDeprecated(bool d);
+
bool isSigned() const;
void setSigned(bool s);
+ QString underlyingType() const;
+ void setUnderlyingType(const QString &underlyingType);
+
private:
+ QString m_underlyingType;
Access m_accessPolicy = Access::Public;
EnumeratorList m_enumerators;
EnumKind m_enumKind = CEnum;
+ bool m_deprecated = false;
bool m_signed = true;
};
class _EnumeratorModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_EnumeratorModelItem)
DECLARE_MODEL_NODE(Enumerator)
- explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind) {}
- explicit _EnumeratorModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind) {}
+ explicit _EnumeratorModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _EnumeratorModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_EnumeratorModelItem();
QString stringValue() const;
@@ -668,6 +658,9 @@ public:
EnumValue value() const { return m_value; }
void setValue(EnumValue v) { m_value = v; }
+ bool isDeprecated() const;
+ void setDeprecated(bool d);
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
@@ -675,17 +668,18 @@ public:
private:
QString m_stringValue;
EnumValue m_value;
+ bool m_deprecated = false;
};
class _TemplateParameterModelItem: public _CodeModelItem
{
public:
+ Q_DISABLE_COPY_MOVE(_TemplateParameterModelItem)
DECLARE_MODEL_NODE(TemplateParameter)
- explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind)
- : _CodeModelItem(model, kind), m_defaultValue(false) {}
- explicit _TemplateParameterModelItem(CodeModel *model, const QString &name, int kind = __node_kind)
- : _CodeModelItem(model, name, kind), m_defaultValue(false) {}
+ explicit _TemplateParameterModelItem(CodeModel *model, int kind = __node_kind);
+ explicit _TemplateParameterModelItem(CodeModel *model, const QString &name,
+ int kind = __node_kind);
~_TemplateParameterModelItem();
TypeInfo type() const;
@@ -700,9 +694,7 @@ public:
private:
TypeInfo m_type;
- bool m_defaultValue;
+ bool m_defaultValue = false;
};
#endif // CODEMODEL_H
-
-// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
index 1a058bdfe..e5c429bd0 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
@@ -4,6 +4,8 @@
#ifndef CODEMODEL_ENUMS_H
#define CODEMODEL_ENUMS_H
+#include <QtCore/qflags.h>
+
enum ReferenceType {
NoReference,
LValueReference,
@@ -43,4 +45,17 @@ enum class Access
Public
};
+enum class FunctionAttribute {
+ Abstract = 0x00000001,
+ Static = 0x00000002,
+ Virtual = 0x00000004,
+ Override = 0x00000008,
+ Final = 0x00000010,
+ Deprecated = 0x00000020, // Code annotation
+ Explicit = 0x00000040, // Constructor
+};
+
+Q_DECLARE_FLAGS(FunctionAttributes, FunctionAttribute)
+Q_DECLARE_OPERATORS_FOR_FLAGS(FunctionAttributes)
+
#endif // CODEMODEL_ENUMS_H
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h
index a3adf6678..f0a25c9db 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel_fwd.h
@@ -7,7 +7,8 @@
#define CODEMODEL_FWD_H
#include <QtCore/QList>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
// forward declarations
class CodeModel;
@@ -27,20 +28,20 @@ class _VariableModelItem;
class _MemberModelItem;
class TypeInfo;
-using ArgumentModelItem = QSharedPointer<_ArgumentModelItem>;
-using ClassModelItem = QSharedPointer<_ClassModelItem>;
-using CodeModelItem = QSharedPointer<_CodeModelItem>;
-using EnumModelItem = QSharedPointer<_EnumModelItem>;
-using EnumeratorModelItem = QSharedPointer<_EnumeratorModelItem>;
-using FileModelItem = QSharedPointer<_FileModelItem>;
-using FunctionModelItem = QSharedPointer<_FunctionModelItem>;
-using NamespaceModelItem = QSharedPointer<_NamespaceModelItem>;
-using ScopeModelItem = QSharedPointer<_ScopeModelItem>;
-using TemplateParameterModelItem = QSharedPointer<_TemplateParameterModelItem>;
-using TypeDefModelItem = QSharedPointer<_TypeDefModelItem>;
-using TemplateTypeAliasModelItem = QSharedPointer<_TemplateTypeAliasModelItem>;
-using VariableModelItem = QSharedPointer<_VariableModelItem>;
-using MemberModelItem = QSharedPointer<_MemberModelItem>;
+using ArgumentModelItem = std::shared_ptr<_ArgumentModelItem>;
+using ClassModelItem = std::shared_ptr<_ClassModelItem>;
+using CodeModelItem = std::shared_ptr<_CodeModelItem>;
+using EnumModelItem = std::shared_ptr<_EnumModelItem>;
+using EnumeratorModelItem = std::shared_ptr<_EnumeratorModelItem>;
+using FileModelItem = std::shared_ptr<_FileModelItem>;
+using FunctionModelItem = std::shared_ptr<_FunctionModelItem>;
+using NamespaceModelItem = std::shared_ptr<_NamespaceModelItem>;
+using ScopeModelItem = std::shared_ptr<_ScopeModelItem>;
+using TemplateParameterModelItem = std::shared_ptr<_TemplateParameterModelItem>;
+using TypeDefModelItem = std::shared_ptr<_TypeDefModelItem>;
+using TemplateTypeAliasModelItem = std::shared_ptr<_TemplateTypeAliasModelItem>;
+using VariableModelItem = std::shared_ptr<_VariableModelItem>;
+using MemberModelItem = std::shared_ptr<_MemberModelItem>;
using ArgumentList = QList<ArgumentModelItem>;
using ClassList = QList<ClassModelItem>;
diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp
index 3fa641e0c..3749e16a8 100644
--- a/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.cpp
@@ -7,12 +7,34 @@
#include <QtCore/QString>
#include <QtCore/QTextStream>
+using namespace Qt::StringLiterals;
+
QString EnumValue::toString() const
{
return m_type == EnumValue::Signed
? QString::number(m_value) : QString::number(m_unsignedValue);
}
+QString EnumValue::toHex(int fieldWidth) const
+{
+ QString result;
+ QTextStream str(&result);
+ // Note: Qt goofes up formatting of negative padded hex numbers, it ends up
+ // with "0x00-1". Write '-' before.
+ if (isNegative())
+ str << '-';
+ str << "0x" << Qt::hex;
+ if (fieldWidth) {
+ str.setFieldWidth(fieldWidth);
+ str.setPadChar(u'0');
+ }
+ if (m_type == EnumValue::Signed)
+ str << qAbs(m_value);
+ else
+ str << m_unsignedValue;
+ return result;
+}
+
void EnumValue::setValue(qint64 v)
{
m_value = v;
@@ -25,11 +47,37 @@ void EnumValue::setUnsignedValue(quint64 v)
m_type = Unsigned;
}
-bool EnumValue::equals(const EnumValue &rhs) const
+EnumValue EnumValue::toUnsigned() const
{
- if (m_type != rhs.m_type)
+ if (m_type == Unsigned)
+ return *this;
+ EnumValue result;
+ result.setUnsignedValue(m_value < 0 ? quint64(-m_value) : quint64(m_value));
+ return result;
+}
+
+bool comparesEqual(const EnumValue &lhs, const EnumValue &rhs) noexcept
+{
+ if (lhs.m_type != rhs.m_type)
return false;
- return m_type == Signed ? m_value == rhs.m_value : m_unsignedValue == rhs.m_unsignedValue;
+ return lhs.m_type == EnumValue::Signed
+ ? lhs.m_value == rhs.m_value : lhs.m_unsignedValue == rhs.m_unsignedValue;
+}
+
+void EnumValue::formatDebugHex(QDebug &d) const
+{
+ d << "0x" << Qt::hex;
+ formatDebug(d);
+ d << Qt::dec;
+}
+
+void EnumValue::formatDebug(QDebug &d) const
+{
+
+ if (m_type == EnumValue::Signed)
+ d << m_value;
+ else
+ d << m_unsignedValue << 'u';
}
#ifndef QT_NO_DEBUG_STREAM
@@ -39,10 +87,7 @@ QDebug operator<<(QDebug d,const EnumValue &v)
d.nospace();
d.noquote();
d << "EnumValue(";
- if (v.m_type == EnumValue::Signed)
- d << v.m_value;
- else
- d << v.m_unsignedValue << 'u';
+ v.formatDebug(d);
d << ')';
return d;
}
diff --git a/sources/shiboken6/ApiExtractor/parser/enumvalue.h b/sources/shiboken6/ApiExtractor/parser/enumvalue.h
index bae2b30bf..bbd5a712d 100644
--- a/sources/shiboken6/ApiExtractor/parser/enumvalue.h
+++ b/sources/shiboken6/ApiExtractor/parser/enumvalue.h
@@ -4,7 +4,9 @@
#ifndef ENUMVALUE_H
#define ENUMVALUE_H
-#include <QtCore/QtGlobal>
+#include <QtCore/qtypes.h>
+#include <QtCore/qtclasshelpermacros.h>
+#include <QtCore/QtCompare>
QT_FORWARD_DECLARE_CLASS(QDebug)
QT_FORWARD_DECLARE_CLASS(QString)
@@ -20,18 +22,29 @@ public:
};
QString toString() const;
+ QString toHex(int fieldWidth = 0) const;
Type type() { return m_type; }
qint64 value() const { return m_value; }
quint64 unsignedValue() const { return m_unsignedValue; }
bool isNullValue() const { return m_type == Signed ? m_value == 0 : m_unsignedValue == 0u; }
+ bool isNegative() const { return m_type == Signed && m_value < 0; }
void setValue(qint64 v);
void setUnsignedValue(quint64 v);
+ EnumValue toUnsigned() const;
+
bool equals(const EnumValue &rhs) const;
+ void formatDebug(QDebug &d) const;
+ void formatDebugHex(QDebug &d) const;
+
private:
+ friend bool comparesEqual(const EnumValue &lhs,
+ const EnumValue &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(EnumValue)
+
#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug, const EnumValue &);
#endif
@@ -45,9 +58,4 @@ private:
Type m_type = Signed;
};
-inline bool operator==(const EnumValue &e1, const EnumValue &e2)
-{ return e1.equals(e2); }
-inline bool operator!=(const EnumValue &e1, const EnumValue &e2)
-{ return !e1.equals(e2); }
-
#endif // ENUMVALUE_H
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
index 2dff569cb..f8c5c31d8 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
@@ -7,6 +7,7 @@
#include "codemodel.h"
#include <clangparser/clangutils.h>
+#include <debughelpers_p.h>
#include "qtcompat.h"
@@ -46,10 +47,10 @@ public:
};
};
- ReferenceType m_referenceType;
+ ReferenceType m_referenceType = NoReference;
};
-TypeInfoData::TypeInfoData() : flags(0), m_referenceType(NoReference)
+TypeInfoData::TypeInfoData() : flags(0)
{
}
@@ -60,9 +61,8 @@ TypeInfo::TypeInfo() : d(new TypeInfoData)
TypeInfo::~TypeInfo() = default;
TypeInfo::TypeInfo(const TypeInfo &) = default;
TypeInfo& TypeInfo::operator=(const TypeInfo &) = default;
-TypeInfo::TypeInfo(TypeInfo &&) = default;
-TypeInfo& TypeInfo::operator=(TypeInfo &&) = default;
-
+TypeInfo::TypeInfo(TypeInfo &&) noexcept = default;
+TypeInfo &TypeInfo::operator=(TypeInfo &&) noexcept = default;
static inline TypeInfo createType(const QString &name)
{
@@ -98,7 +98,7 @@ TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs)
__result.setArrayElements(__result.arrayElements() + __rhs.arrayElements());
- const auto instantiations = __rhs.instantiations();
+ const auto &instantiations = __rhs.instantiations();
for (const auto &i : instantiations)
__result.addInstantiation(i);
@@ -266,6 +266,12 @@ void TypeInfo::clearInstantiations()
d->m_instantiations.clear();
}
+bool TypeInfo::isPlain() const
+{
+ return d->m_constant == 0 && d->m_volatile == 0 && d->m_referenceType == NoReference
+ && d->m_indirections.isEmpty() && d->m_arrayElements.isEmpty();
+}
+
TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope)
{
CodeModel *__model = __scope->model();
@@ -286,14 +292,14 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con
otherType.setQualifiedName(__item->qualifiedName());
}
- if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_TypeDefModelItem>(__item)) {
+ if (TypeDefModelItem __typedef = std::dynamic_pointer_cast<_TypeDefModelItem>(__item)) {
const TypeInfo combined = TypeInfo::combine(__typedef->type(), otherType);
const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope);
if (!nextItem)
return combined;
// PYSIDE-362, prevent recursion on opaque structs like
// typedef struct xcb_connection_t xcb_connection_t;
- if (nextItem.data() ==__item.data()) {
+ if (nextItem.get() ==__item.get()) {
std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__
<< "() on " << qPrintable(__type.qualifiedName().join(u"::"_s))
<< std::endl;
@@ -302,18 +308,18 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, con
return resolveType(nextItem, combined, __scope);
}
- if (TemplateTypeAliasModelItem templateTypeAlias = qSharedPointerDynamicCast<_TemplateTypeAliasModelItem>(__item)) {
+ if (TemplateTypeAliasModelItem templateTypeAlias = std::dynamic_pointer_cast<_TemplateTypeAliasModelItem>(__item)) {
TypeInfo combined = TypeInfo::combine(templateTypeAlias->type(), otherType);
// For the alias "template<typename T> using QList = QVector<T>" with
// other="QList<int>", replace the instantiations to obtain "QVector<int>".
auto aliasInstantiations = templateTypeAlias->type().instantiations();
const auto &concreteInstantiations = otherType.instantiations();
- const int count = qMin(aliasInstantiations.size(), concreteInstantiations.size());
- for (int i = 0; i < count; ++i)
- aliasInstantiations[i] = concreteInstantiations[i];
+ const auto count = qMin(aliasInstantiations.size(), concreteInstantiations.size());
+ for (qsizetype i = 0; i < count; ++i)
+ aliasInstantiations[i] = concreteInstantiations.at(i);
combined.setInstantiations(aliasInstantiations);
- const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope);
+ const CodeModelItem nextItem = CodeModel::findItem(combined.qualifiedName(), __scope);
if (!nextItem)
return combined;
return resolveType(nextItem, combined, __scope);
@@ -341,6 +347,10 @@ public:
while (level < m_parseStack.size())
m_parseStack.pop();
TypeInfo instantiation;
+ if (name.startsWith(u"const ")) {
+ instantiation.setConstant(true);
+ name = name.mid(6);
+ }
instantiation.setQualifiedName(qualifiedName(name));
top()->addInstantiation(instantiation);
}
@@ -361,7 +371,8 @@ private:
QStack<TypeInfo *> m_parseStack;
};
-QPair<int, int> TypeInfo::parseTemplateArgumentList(const QString &l, int from)
+std::pair<qsizetype, qsizetype>
+ TypeInfo::parseTemplateArgumentList(const QString &l, qsizetype from)
{
return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from);
}
@@ -377,9 +388,9 @@ QString TypeInfo::toString() const
tmp += d->m_qualifiedName.join(u"::"_s);
- if (const int instantiationCount = d->m_instantiations.size()) {
+ if (const auto instantiationCount = d->m_instantiations.size()) {
tmp += u'<';
- for (int i = 0; i < instantiationCount; ++i) {
+ for (qsizetype i = 0; i < instantiationCount; ++i) {
if (i)
tmp += u", "_s;
tmp += d->m_instantiations.at(i).toString();
@@ -441,34 +452,31 @@ bool TypeInfoData::equals(const TypeInfoData &other) const
&& m_instantiations == other.m_instantiations;
}
-bool TypeInfo::equals(const TypeInfo &other) const
+
+bool comparesEqual(const TypeInfo &lhs, const TypeInfo &rhs) noexcept
{
- return d.data() == other.d.data() || d->equals(*other.d);
+ return lhs.d.data() == rhs.d.data() || lhs.d->equals(*rhs.d);
}
QString TypeInfo::indirectionKeyword(Indirection i)
{
- return i == Indirection::Pointer
- ? QStringLiteral("*") : QStringLiteral("*const");
+ return i == Indirection::Pointer ? "*"_L1 : "*const"_L1;
}
-static inline QString constQualifier() { return QStringLiteral("const"); }
-static inline QString volatileQualifier() { return QStringLiteral("volatile"); }
-
bool TypeInfo::stripLeadingConst(QString *s)
{
- return stripLeadingQualifier(constQualifier(), s);
+ return stripLeadingQualifier("const"_L1, s);
}
bool TypeInfo::stripLeadingVolatile(QString *s)
{
- return stripLeadingQualifier(volatileQualifier(), s);
+ return stripLeadingQualifier("volatile"_L1, s);
}
-bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s)
+bool TypeInfo::stripLeadingQualifier(QLatin1StringView qualifier, QString *s)
{
// "const int x"
- const int qualifierSize = qualifier.size();
+ const auto qualifierSize = qualifier.size();
if (s->size() < qualifierSize + 1 || !s->startsWith(qualifier)
|| !s->at(qualifierSize).isSpace()) {
return false;
@@ -514,7 +522,7 @@ void TypeInfoData::simplifyStdType()
Q_ASSERT(isStdType());
if (m_qualifiedName.at(1).startsWith(u"__"))
m_qualifiedName.removeAt(1);
- for (int t = m_instantiations.size() - 1; t >= 0; --t) {
+ for (auto t = m_instantiations.size() - 1; t >= 0; --t) {
if (m_instantiations.at(t).isStdType()) {
if (discardStdType(m_instantiations.at(t).qualifiedName().constLast()))
m_instantiations.removeAt(t);
@@ -558,16 +566,6 @@ void TypeInfo::formatTypeSystemSignature(QTextStream &str) const
}
#ifndef QT_NO_DEBUG_STREAM
-template <class It>
-void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ")
-{
- for (It i = i1; i != i2; ++i) {
- if (i != i1)
- d << separator;
- d << *i;
- }
-}
-
void TypeInfo::formatDebug(QDebug &debug) const
{
debug << '"';
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
index e015647fa..e4f363b67 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
@@ -10,8 +10,11 @@
#include <QtCore/QString>
#include <QtCore/QSharedDataPointer>
+#include <QtCore/QtCompare>
#include <QtCore/QStringList>
+#include <utility>
+
QT_FORWARD_DECLARE_CLASS(QDebug)
QT_FORWARD_DECLARE_CLASS(QTextStream)
@@ -28,8 +31,8 @@ public:
~TypeInfo();
TypeInfo(const TypeInfo &);
TypeInfo& operator=(const TypeInfo &);
- TypeInfo(TypeInfo &&);
- TypeInfo& operator=(TypeInfo &&);
+ TypeInfo(TypeInfo &&) noexcept;
+ TypeInfo &operator=(TypeInfo &&) noexcept;
static TypeInfo voidType();
static TypeInfo varArgsType();
@@ -77,11 +80,12 @@ public:
void addInstantiation(const TypeInfo &i);
void clearInstantiations();
- bool isStdType() const;
+ bool isPlain() const; // neither const,volatile, no indirections/references, array
- QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0);
+ bool isStdType() const;
- bool equals(const TypeInfo &other) const;
+ std::pair<qsizetype, qsizetype>
+ parseTemplateArgumentList(const QString &l, qsizetype from = 0);
// ### arrays and templates??
@@ -100,12 +104,16 @@ public:
static bool stripLeadingConst(QString *s);
static bool stripLeadingVolatile(QString *s);
- static bool stripLeadingQualifier(const QString &qualifier, QString *s);
+ static bool stripLeadingQualifier(QLatin1StringView qualifier, QString *s);
static void stripQualifiers(QString *s);
void simplifyStdType();
private:
+ friend bool comparesEqual(const TypeInfo &lhs,
+ const TypeInfo &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(TypeInfo)
+
QSharedDataPointer<TypeInfoData> d;
friend class TypeInfoTemplateArgumentHandler;
@@ -113,12 +121,6 @@ private:
static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope);
};
-inline bool operator==(const TypeInfo &t1, const TypeInfo &t2)
-{ return t1.equals(t2); }
-
-inline bool operator!=(const TypeInfo &t1, const TypeInfo &t2)
-{ return !t1.equals(t2); }
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const TypeInfo &t);
#endif
diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.cpp b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
index f1b23c240..992f735ac 100644
--- a/sources/shiboken6/ApiExtractor/predefined_templates.cpp
+++ b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
@@ -10,7 +10,7 @@ using namespace Qt::StringLiterals;
static QString pySequenceToCppContainer(const QString &insertFunc,
bool reserve)
{
- QString result;
+ QString result = u"(%out).clear();\n"_s;
if (reserve) {
result += uR"(if (PyList_Check(%in)) {
const Py_ssize_t size = PySequence_Size(%in);
@@ -39,20 +39,37 @@ while (true) {
return result;
}
-static const char stlMapKeyAccessor[] = "->first";
-static const char stlMapValueAccessor[] = "->second";
-static const char qtMapKeyAccessor[] = ".key()";
-static const char qtMapValueAccessor[] = ".value()";
+// Convert a sequence to a limited/fixed array
+static QString pySequenceToCppArray()
+{
+ return uR"(Shiboken::AutoDecRef it(PyObject_GetIter(%in));
+for (auto oit = std::begin(%out), oend = std::end(%out); oit != oend; ++oit) {
+ Shiboken::AutoDecRef pyItem(PyIter_Next(it.object()));
+ if (pyItem.isNull()) {
+ if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
+ PyErr_Clear();
+ break;
+ }
+ %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem);
+ *oit = cppItem;
+}
+)"_s;
+}
+
+static constexpr auto stlMapKeyAccessor = "->first"_L1;
+static constexpr auto stlMapValueAccessor = "->second"_L1;
+static constexpr auto qtMapKeyAccessor = ".key()"_L1;
+static constexpr auto qtMapValueAccessor = ".value()"_L1;
static QString cppMapToPyDict(bool isQMap)
{
return uR"(PyObject *%out = PyDict_New();
-for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it) {
+for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it) {
const auto &key = it)"_s
- + QLatin1StringView(isQMap ? qtMapKeyAccessor : stlMapKeyAccessor)
+ + (isQMap ? qtMapKeyAccessor : stlMapKeyAccessor)
+ uR"(;
const auto &value = it)"_s
- + QLatin1StringView(isQMap ? qtMapValueAccessor : stlMapValueAccessor)
+ + (isQMap ? qtMapValueAccessor : stlMapValueAccessor)
+ uR"(;
PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
PyObject *pyValue = %CONVERTTOPYTHON[%INTYPE_1](value);
@@ -68,6 +85,7 @@ static QString pyDictToCppMap(bool isQMap)
{
return uR"(PyObject *key;
PyObject *value;
+%out.clear();
Py_ssize_t pos = 0;
while (PyDict_Next(%in, &pos, &key, &value)) {
%OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
@@ -83,9 +101,9 @@ while (PyDict_Next(%in, &pos, &key, &value)) {
static QString cppMultiMapToPyDict(bool isQMultiMap)
{
return uR"(PyObject *%out = PyDict_New();
- for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) {
+ for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) {
const auto &key = it)"_s
- + QLatin1StringView(isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor)
+ + (isQMultiMap ? qtMapKeyAccessor : stlMapKeyAccessor)
+ uR"(;
PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
auto upper = %in.)"_s
@@ -109,9 +127,9 @@ static QString cppMultiMapToPyDict(bool isQMultiMap)
static QString cppMultiHashToPyDict(bool isQMultiHash)
{
return uR"(PyObject *%out = PyDict_New();
- for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) {
+ for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ) {
const auto &key = it)"_s
- + QLatin1StringView(isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor)
+ + (isQMultiHash ? qtMapKeyAccessor : stlMapKeyAccessor)
+ uR"(;
PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
auto range = %in.equal_range(key);
@@ -134,6 +152,7 @@ static QString pyDictToCppMultiHash(bool isQMultiHash)
{
return uR"(PyObject *key;
PyObject *values;
+ %out.clear();
Py_ssize_t pos = 0;
while (PyDict_Next(%in, &pos, &key, &values)) {
%OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
@@ -172,7 +191,7 @@ return %out;
{u"shiboken_conversion_cppsequence_to_pylist"_s,
uR"(PyObject *%out = PyList_New(Py_ssize_t(%in.size()));
Py_ssize_t idx = 0;
-for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it, ++idx) {
+for (auto it = std::cbegin(%in), end = std::cend(%in); it != end; ++it, ++idx) {
const auto &cppItem = *it;
PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem));
}
@@ -190,6 +209,8 @@ return %out;)"_s},
pySequenceToCppContainer(u"push_back"_s, false)},
{u"shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve"_s,
pySequenceToCppContainer(u"push_back"_s, true)},
+ {u"shiboken_conversion_pyiterable_to_cpparray"_s,
+ pySequenceToCppArray()},
{u"shiboken_conversion_pyiterable_to_cppsetcontainer"_s,
pySequenceToCppContainer(u"insert"_s, false)},
@@ -231,19 +252,25 @@ QByteArray containerTypeSystemSnippet(const char *name, const char *type,
const char *targetToNativeType,
const char *targetToNative)
{
- return QByteArrayLiteral("<container-type name=\"")
+ QByteArray result = QByteArrayLiteral("<container-type name=\"")
+ name + QByteArrayLiteral("\" type=\"") + type + R"(">
<include file-name=")" + include + R"(" location="global"/>
<conversion-rule>
<native-to-target>
<insert-template name=")" + nativeToTarget + R"("/>
</native-to-target>
- <target-to-native>
- <add-conversion type=")" + targetToNativeType + R"(">
- <insert-template name=")" + targetToNative + R"("/>
+)";
+ if (targetToNativeType != nullptr) {
+ result += QByteArrayLiteral(R"( <target-to-native>
+ <add-conversion type=")") + targetToNativeType
+ + QByteArrayLiteral(R"(">
+ <insert-template name=")") + targetToNative + QByteArrayLiteral(R"("/>
</add-conversion>
</target-to-native>
- </conversion-rule>
+)");
+ }
+result += QByteArrayLiteral(R"( </conversion-rule>
</container-type>
-)";
+)");
+ return result;
}
diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.h b/sources/shiboken6/ApiExtractor/predefined_templates.h
index 2519f65d9..0cc2c7f32 100644
--- a/sources/shiboken6/ApiExtractor/predefined_templates.h
+++ b/sources/shiboken6/ApiExtractor/predefined_templates.h
@@ -21,7 +21,7 @@ const PredefinedTemplates &predefinedTemplates();
QByteArray containerTypeSystemSnippet(const char *name, const char *type,
const char *include,
const char *nativeToTarget,
- const char *targetToNativeType,
- const char *targetToNative);
+ const char *targetToNativeType = nullptr,
+ const char *targetToNative = nullptr);
#endif // PREDEFINED_TEMPLATES_H
diff --git a/sources/shiboken6/ApiExtractor/primitivetypeentry.h b/sources/shiboken6/ApiExtractor/primitivetypeentry.h
index d0b50aa9c..6faaf7a61 100644
--- a/sources/shiboken6/ApiExtractor/primitivetypeentry.h
+++ b/sources/shiboken6/ApiExtractor/primitivetypeentry.h
@@ -5,6 +5,7 @@
#define PRIMITIVETYPEENTRY_H
#include "typesystem.h"
+#include "customconversion_typedefs.h"
class PrimitiveTypeEntryPrivate;
@@ -15,7 +16,7 @@ class PrimitiveTypeEntry : public TypeEntry
{
public:
explicit PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
QString defaultConstructor() const;
void setDefaultConstructor(const QString& defaultConstructor);
@@ -27,25 +28,13 @@ public:
* \return the type referenced by the typedef, or a null pointer
* if the current object is not an typedef
*/
- PrimitiveTypeEntry *referencedTypeEntry() const;
+ PrimitiveTypeEntryPtr referencedTypeEntry() const;
/**
* Defines type referenced by this entry.
* \param referencedTypeEntry type referenced by this entry
*/
- void setReferencedTypeEntry(PrimitiveTypeEntry* referencedTypeEntry);
-
- /// Finds the most basic primitive type that the typedef represents,
- /// i.e. a type that is not an typedef'ed.
- /// \return the most basic non-typedef'ed primitive type represented
- /// by this typedef or self in case it is not a reference.
- const PrimitiveTypeEntry* basicReferencedTypeEntry() const;
-
- /// Finds the basic primitive type that the typedef represents
- /// and was explicitly specified in the type system.
- /// \return the basic primitive type that was explicitly specified in
- /// the type system.
- const PrimitiveTypeEntry* basicReferencedNonBuiltinTypeEntry() const;
+ void setReferencedTypeEntry(PrimitiveTypeEntryPtr referencedTypeEntry);
/// Returns whether this entry references another entry.
bool referencesType() const;
@@ -53,6 +42,10 @@ public:
bool preferredTargetLangType() const;
void setPreferredTargetLangType(bool b);
+ bool hasCustomConversion() const;
+ void setCustomConversion(const CustomConversionPtr &customConversion);
+ CustomConversionPtr customConversion() const;
+
TypeEntry *clone() const override;
#ifndef QT_NO_DEBUG_STREAM
@@ -63,4 +56,17 @@ protected:
explicit PrimitiveTypeEntry(PrimitiveTypeEntryPrivate *d);
};
+/// Finds the most basic primitive type that the typedef represents,
+/// i.e. a type that is not an typedef'ed.
+/// \return the most basic non-typedef'ed primitive type represented
+/// by this typedef or self in case it is not a reference.
+PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const PrimitiveTypeEntryCPtr &e);
+PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const TypeEntryCPtr &e);
+
+/// Finds the basic primitive type that the typedef represents
+/// and was explicitly specified in the type system.
+/// \return the basic primitive type that was explicitly specified in
+/// the type system.
+PrimitiveTypeEntryCPtr basicReferencedNonBuiltinTypeEntry(const PrimitiveTypeEntryCPtr &e);
+
#endif // PRIMITIVETYPEENTRY_H
diff --git a/sources/shiboken6/ApiExtractor/propertyspec.cpp b/sources/shiboken6/ApiExtractor/propertyspec.cpp
index 54ac6fdab..32b756fad 100644
--- a/sources/shiboken6/ApiExtractor/propertyspec.cpp
+++ b/sources/shiboken6/ApiExtractor/propertyspec.cpp
@@ -5,9 +5,10 @@
#include "abstractmetalang.h"
#include "abstractmetabuilder_p.h"
#include "abstractmetatype.h"
-#include "codemodel.h"
+#include "documentation.h"
#include "messages.h"
#include "complextypeentry.h"
+#include "typeinfo.h"
#include "qtcompat.h"
@@ -31,6 +32,7 @@ public:
m_write(ts.write),
m_designable(ts.designable),
m_reset(ts.reset),
+ m_notify(ts.notify),
m_type(type),
m_generateGetSetDef(ts.generateGetSetDef)
{
@@ -41,6 +43,8 @@ public:
QString m_write;
QString m_designable;
QString m_reset;
+ QString m_notify;
+ Documentation m_documentation;
AbstractMetaType m_type;
int m_index = -1;
// Indicates whether actual code is generated instead of relying on libpyside.
@@ -55,8 +59,8 @@ QPropertySpec::QPropertySpec(const TypeSystemProperty &ts,
QPropertySpec::QPropertySpec(const QPropertySpec &) = default;
QPropertySpec &QPropertySpec::operator=(const QPropertySpec &) = default;
-QPropertySpec::QPropertySpec(QPropertySpec &&) = default;
-QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) = default;
+QPropertySpec::QPropertySpec(QPropertySpec &&) noexcept = default;
+QPropertySpec &QPropertySpec::operator=(QPropertySpec &&) noexcept = default;
QPropertySpec::~QPropertySpec() = default;
const AbstractMetaType &QPropertySpec::type() const
@@ -70,7 +74,7 @@ void QPropertySpec::setType(const AbstractMetaType &t)
d->m_type = t;
}
-const TypeEntry *QPropertySpec::typeEntry() const
+TypeEntryCPtr QPropertySpec::typeEntry() const
{
return d->m_type.typeEntry();
}
@@ -86,6 +90,17 @@ void QPropertySpec::setName(const QString &name)
d->m_name = name;
}
+Documentation QPropertySpec::documentation() const
+{
+ return d->m_documentation;
+}
+
+void QPropertySpec::setDocumentation(const Documentation &doc)
+{
+ if (d->m_documentation != doc)
+ d->m_documentation = doc;
+}
+
QString QPropertySpec::read() const
{
return d->m_read;
@@ -135,6 +150,17 @@ void QPropertySpec::setReset(const QString &reset)
d->m_reset = reset;
}
+QString QPropertySpec::notify() const
+{
+ return d->m_notify;
+}
+
+void QPropertySpec::setNotify(const QString &notify)
+{
+ if (d->m_notify != notify)
+ d->m_notify = notify;
+}
+
int QPropertySpec::index() const
{
return d->m_index;
@@ -163,13 +189,15 @@ void QPropertySpec::setGenerateGetSetDef(bool generateGetSetDef)
TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString &declarationIn,
QString *errorMessage)
{
- enum class PropertyToken { None, Read, Write, Designable, Reset };
+ enum class PropertyToken { None, Read, Write, Designable, Reset, Notify, Member };
static const QHash<QString, PropertyToken> tokenLookup = {
- {QStringLiteral("READ"), PropertyToken::Read},
- {QStringLiteral("WRITE"), PropertyToken::Write},
- {QStringLiteral("DESIGNABLE"), PropertyToken::Designable},
- {QStringLiteral("RESET"), PropertyToken::Reset}
+ {"READ"_L1, PropertyToken::Read},
+ {"WRITE"_L1, PropertyToken::Write},
+ {"DESIGNABLE"_L1, PropertyToken::Designable},
+ {"RESET"_L1, PropertyToken::Reset},
+ {"NOTIFY"_L1, PropertyToken::Notify},
+ {"MEMBER"_L1, PropertyToken::Member}
};
errorMessage->clear();
@@ -192,13 +220,13 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString
return result;
}
- const int firstToken = int(it - propertyTokens.cbegin());
+ const auto firstToken = qsizetype(it - propertyTokens.cbegin());
if (firstToken < 2) {
*errorMessage = u"Insufficient number of tokens in property specification"_s;
return result;
}
- for (int pos = firstToken; pos + 1 < propertyTokens.size(); pos += 2) {
+ for (qsizetype pos = firstToken; pos + 1 < propertyTokens.size(); pos += 2) {
switch (tokenLookup.value(propertyTokens.at(pos))) {
case PropertyToken::Read:
result.read = propertyTokens.at(pos + 1);
@@ -212,16 +240,24 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString
case PropertyToken::Designable:
result.designable = propertyTokens.at(pos + 1);
break;
+ case PropertyToken::Notify:
+ result.notify = propertyTokens.at(pos + 1);
+ break;
+ case PropertyToken::Member:
+ // Ignore MEMBER tokens introduced by QTBUG-16852 as Python
+ // properties are anyways generated for fields.
+ return {};
+
case PropertyToken::None:
break;
}
}
- const int namePos = firstToken - 1;
+ const auto namePos = firstToken - 1;
result.name = propertyTokens.at(namePos);
result.type = propertyTokens.constFirst();
- for (int pos = 1; pos < namePos; ++pos)
+ for (qsizetype pos = 1; pos < namePos; ++pos)
result.type += u' ' + propertyTokens.at(pos);
// Fix errors like "Q_PROPERTY(QXYSeries *series .." to be of type "QXYSeries*"
@@ -238,7 +274,7 @@ TypeSystemProperty QPropertySpec::typeSystemPropertyFromQ_Property(const QString
// the AbstractMetaType from the type string.
std::optional<QPropertySpec>
QPropertySpec::fromTypeSystemProperty(AbstractMetaBuilderPrivate *b,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const TypeSystemProperty &ts,
const QStringList &scopes,
QString *errorMessage)
@@ -254,7 +290,7 @@ std::optional<QPropertySpec>
auto type = b->translateType(info, metaClass, {}, &typeError);
if (!type.has_value()) {
const QStringList qualifiedName = info.qualifiedName();
- for (int j = scopes.size(); j >= 0 && !type; --j) {
+ for (auto j = scopes.size(); j >= 0 && !type; --j) {
info.setQualifiedName(scopes.mid(0, j) + qualifiedName);
type = b->translateType(info, metaClass, {}, &typeError);
}
@@ -271,7 +307,7 @@ std::optional<QPropertySpec>
// via TypeSystemProperty.
std::optional<QPropertySpec>
QPropertySpec::parseQ_Property(AbstractMetaBuilderPrivate *b,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const QString &declarationIn,
const QStringList &scopes,
QString *errorMessage)
@@ -294,6 +330,8 @@ void QPropertySpec::formatDebug(QDebug &debug) const
debug << ", reset=" << d->m_reset;
if (!d->m_designable.isEmpty())
debug << ", designable=" << d->m_designable;
+ if (!d->m_documentation.isEmpty())
+ debug << ", doc=\"" << d->m_documentation << '"';
}
QDebug operator<<(QDebug d, const QPropertySpec &p)
diff --git a/sources/shiboken6/ApiExtractor/propertyspec.h b/sources/shiboken6/ApiExtractor/propertyspec.h
index b32d6c08a..9e2e0f3d4 100644
--- a/sources/shiboken6/ApiExtractor/propertyspec.h
+++ b/sources/shiboken6/ApiExtractor/propertyspec.h
@@ -6,6 +6,9 @@
class AbstractMetaType;
+#include "abstractmetalang_typedefs.h"
+#include "typesystem_typedefs.h"
+
#include <QtCore/QStringList>
#include <QtCore/QSharedDataPointer>
@@ -14,6 +17,7 @@ class AbstractMetaType;
class AbstractMetaClass;
class AbstractMetaBuilderPrivate;
class AbstractMetaType;
+class Documentation;
class TypeEntry;
struct TypeSystemProperty;
@@ -29,8 +33,8 @@ public:
const AbstractMetaType &type);
QPropertySpec(const QPropertySpec &);
QPropertySpec &operator=(const QPropertySpec &);
- QPropertySpec(QPropertySpec &&);
- QPropertySpec &operator=(QPropertySpec &&);
+ QPropertySpec(QPropertySpec &&) noexcept;
+ QPropertySpec &operator=(QPropertySpec &&) noexcept;
~QPropertySpec();
static TypeSystemProperty typeSystemPropertyFromQ_Property(const QString &declarationIn,
@@ -39,14 +43,14 @@ public:
static std::optional<QPropertySpec>
fromTypeSystemProperty(AbstractMetaBuilderPrivate *b,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const TypeSystemProperty &ts,
const QStringList &scopes,
QString *errorMessage);
static std::optional<QPropertySpec>
parseQ_Property(AbstractMetaBuilderPrivate *b,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const QString &declarationIn,
const QStringList &scopes,
QString *errorMessage);
@@ -54,11 +58,14 @@ public:
const AbstractMetaType &type() const;
void setType(const AbstractMetaType &t);
- const TypeEntry *typeEntry() const;
+ TypeEntryCPtr typeEntry() const;
QString name() const;
void setName(const QString &name);
+ Documentation documentation() const;
+ void setDocumentation(const Documentation &doc);
+
QString read() const;
void setRead(const QString &read);
@@ -72,6 +79,9 @@ public:
QString reset() const;
void setReset(const QString &reset);
+ QString notify() const; // Q_PROPERTY/C++ only
+ void setNotify(const QString &notify);
+
int index() const;
void setIndex(int index);
diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp
index 3e7cc2a33..64d44378b 100644
--- a/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp
+++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.cpp
@@ -6,10 +6,15 @@
#include <QtCore/QDebug>
+TextStream &operator<<(TextStream &str, const castToPyCFunction &c)
+{
+ str << "reinterpret_cast<PyCFunction>(" << c.m_function << ')';
+ return str;
+}
+
TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e)
{
- s << "{\"" << e.name << "\", reinterpret_cast<PyCFunction>("
- << e.function << "), ";
+ s << "{\"" << e.name << "\", " << castToPyCFunction(e.function) <<", ";
if (e.methFlags.isEmpty()) {
s << '0';
} else {
@@ -19,7 +24,9 @@ TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e)
s << e.methFlags.at(i);
}
}
- if (!e.doc.isEmpty())
+ if (e.doc.isEmpty())
+ s << ", nullptr";
+ else
s << ", R\"(" << e.doc << ")\"";
s << '}';
return s;
diff --git a/sources/shiboken6/ApiExtractor/pymethoddefentry.h b/sources/shiboken6/ApiExtractor/pymethoddefentry.h
index 54eaa4ce1..a8694eb30 100644
--- a/sources/shiboken6/ApiExtractor/pymethoddefentry.h
+++ b/sources/shiboken6/ApiExtractor/pymethoddefentry.h
@@ -11,6 +11,14 @@ QT_FORWARD_DECLARE_CLASS(QDebug)
class TextStream;
+struct castToPyCFunction
+{
+ explicit castToPyCFunction(QAnyStringView function) noexcept :
+ m_function(function) {}
+
+ QAnyStringView m_function;
+};
+
struct PyMethodDefEntry
{
QString name;
@@ -21,6 +29,7 @@ struct PyMethodDefEntry
using PyMethodDefEntries = QList<PyMethodDefEntry>;
+TextStream &operator<<(TextStream &str, const castToPyCFunction &e);
TextStream &operator<<(TextStream &s, const PyMethodDefEntry &e);
TextStream &operator<<(TextStream &s, const PyMethodDefEntries &e);
diff --git a/sources/shiboken6/ApiExtractor/pythontypeentry.h b/sources/shiboken6/ApiExtractor/pythontypeentry.h
index f1d12e6fd..2e0fbda97 100644
--- a/sources/shiboken6/ApiExtractor/pythontypeentry.h
+++ b/sources/shiboken6/ApiExtractor/pythontypeentry.h
@@ -5,6 +5,7 @@
#define PYTHONTYPEENTRY_H
#include "customtypenentry.h"
+#include "typesystem_enums.h"
class PythonTypeEntry : public CustomTypeEntry
{
diff --git a/sources/shiboken6/ApiExtractor/qtcompat.h b/sources/shiboken6/ApiExtractor/qtcompat.h
index 9627bb76c..3837dcfd2 100644
--- a/sources/shiboken6/ApiExtractor/qtcompat.h
+++ b/sources/shiboken6/ApiExtractor/qtcompat.h
@@ -4,7 +4,7 @@
#ifndef QTCOMPAT_H
#define QTCOMPAT_H
-#include <QtCore/QtGlobal>
+#include <QtCore/qtconfigmacros.h>
#if QT_VERSION < 0x060400
diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
index b20a53632..5bd99bbd8 100644
--- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp
+++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
@@ -3,10 +3,11 @@
#include "qtdocparser.h"
#include "classdocumentation.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
-#include "abstractmetafield.h"
#include "abstractmetafunction.h"
#include "abstractmetalang.h"
+#include "abstractmetatype.h"
#include "documentation.h"
#include "modifications.h"
#include "messages.h"
@@ -14,6 +15,8 @@
#include "reporthandler.h"
#include "flagstypeentry.h"
#include "complextypeentry.h"
+#include "functiontypeentry.h"
+#include "enumtypeentry.h"
#include "qtcompat.h"
@@ -25,8 +28,9 @@ using namespace Qt::StringLiterals;
enum { debugFunctionSearch = 0 };
-static inline QString briefStartElement() { return QStringLiteral("<brief>"); }
-static inline QString briefEndElement() { return QStringLiteral("</brief>"); }
+constexpr auto briefStartElement = "<brief>"_L1;
+constexpr auto briefEndElement = "</brief>"_L1;
+constexpr auto webxmlSuffix = ".webxml"_L1;
Documentation QtDocParser::retrieveModuleDocumentation()
{
@@ -56,7 +60,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str,
case AbstractMetaType::FlagsPattern: {
// Modify qualified name "QFlags<Qt::AlignmentFlag>" with name "Alignment"
// to "Qt::Alignment" as seen by qdoc.
- const auto *flagsEntry = static_cast<const FlagsTypeEntry *>(metaType.typeEntry());
+ const auto flagsEntry = std::static_pointer_cast<const FlagsTypeEntry>(metaType.typeEntry());
QString name = flagsEntry->qualifiedCppName();
if (name.endsWith(u'>') && name.startsWith(u"QFlags<")) {
const int lastColon = name.lastIndexOf(u':');
@@ -73,7 +77,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str,
case AbstractMetaType::ContainerPattern: { // QVector<int>
str << metaType.typeEntry()->qualifiedCppName() << '<';
const auto instantiations = metaType.instantiations();
- for (int i = 0, size = instantiations.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) {
if (i)
str << ", ";
const auto &instantiation = instantiations.at(i);
@@ -99,51 +103,34 @@ static QString formatFunctionArgTypeQuery(const AbstractMetaType &metaType)
return result;
}
-QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
- const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
- const AbstractMetaFunctionCPtr &func,
- const DocModificationList &signedModifs,
- QString *errorMessage)
+QString QtDocParser::functionDocumentation(const QString &sourceFileName,
+ const ClassDocumentation &classDocumentation,
+ const AbstractMetaClassCPtr &metaClass,
+ const AbstractMetaFunctionCPtr &func,
+ QString *errorMessage)
{
errorMessage->clear();
- DocModificationList funcModifs;
- for (const DocModification &funcModif : signedModifs) {
- if (funcModif.signature() == func->minimalSignature())
- funcModifs.append(funcModif);
- }
-
const QString docString =
queryFunctionDocumentation(sourceFileName, classDocumentation, metaClass,
func, errorMessage);
+ const auto funcModifs = DocParser::getXpathDocModifications(func, metaClass);
return docString.isEmpty() || funcModifs.isEmpty()
? docString : applyDocModifications(funcModifs, docString);
}
QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaFunctionCPtr &func,
QString *errorMessage)
{
- // Properties
- if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) {
- const QPropertySpec &prop = metaClass->propertySpecs().at(func->propertySpecIndex());
- const auto index = classDocumentation.indexOfProperty(prop.name());
- if (index == -1) {
- *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data());
- return {};
- }
- return classDocumentation.properties.at(index).description;
- }
-
// Search candidates by name and const-ness
FunctionDocumentationList candidates =
classDocumentation.findFunctionCandidates(func->name(), func->isConstant());
if (candidates.isEmpty()) {
- *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data())
+ *errorMessage = msgCannotFindDocumentation(sourceFileName, func.get())
+ u" (no matches)"_s;
return {};
}
@@ -188,13 +175,13 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
candidates.erase(pend, candidates.end());
if (candidates.size() == 1) {
const auto &match = candidates.constFirst();
- QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.data())
+ QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.get())
<< "\n Falling back to \"" << match.signature
<< "\" obtained by matching the argument count only.";
return candidates.constFirst().description;
}
- QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.data())
+ QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.get())
<< " (" << candidates.size() << " candidates matching the argument count)";
return {};
}
@@ -203,29 +190,100 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
// from the source.
static QString extractBrief(QString *value)
{
- const auto briefStart = value->indexOf(briefStartElement());
+ const auto briefStart = value->indexOf(briefStartElement);
if (briefStart < 0)
return {};
- const auto briefEnd = value->indexOf(briefEndElement(),
- briefStart + briefStartElement().size());
+ const auto briefEnd = value->indexOf(briefEndElement,
+ briefStart + briefStartElement.size());
if (briefEnd < briefStart)
return {};
- const auto briefLength = briefEnd + briefEndElement().size() - briefStart;
+ const auto briefLength = briefEnd + briefEndElement.size() - briefStart;
QString briefValue = value->mid(briefStart, briefLength);
- briefValue.insert(briefValue.size() - briefEndElement().size(),
+ briefValue.insert(briefValue.size() - briefEndElement.size(),
u"<rst> More_...</rst>"_s);
value->remove(briefStart, briefLength);
return briefValue;
}
-void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
+// Find the webxml file for global functions/enums
+// by the doc-file typesystem attribute or via include file.
+static QString findGlobalWebXmLFile(const QString &documentationDataDirectory,
+ const QString &docFile,
+ const Include &include)
+{
+ QString result;
+ if (!docFile.isEmpty()) {
+ result = documentationDataDirectory + u'/' + docFile;
+ if (!result.endsWith(webxmlSuffix))
+ result += webxmlSuffix;
+ return QFileInfo::exists(result) ? result : QString{};
+ }
+ if (include.name().isEmpty())
+ return {};
+ // qdoc "\headerfile <QtLogging>" directive produces "qtlogging.webxml"
+ result = documentationDataDirectory + u'/' +
+ QFileInfo(include.name()).baseName() + webxmlSuffix;
+ if (QFileInfo::exists(result))
+ return result;
+ // qdoc "\headerfile <qdrawutil.h>" produces "qdrawutil-h.webxml"
+ result.insert(result.size() - webxmlSuffix.size(), "-h"_L1);
+ return QFileInfo::exists(result) ? result : QString{};
+}
+
+void QtDocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f)
+{
+ auto te = f->typeEntry();
+ if (te == nullptr)
+ return;
+
+ const QString sourceFileName =
+ findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include());
+ if (sourceFileName.isEmpty())
+ return;
+
+ QString errorMessage;
+ auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ return;
+ }
+ const QString detailed =
+ functionDocumentation(sourceFileName, classDocumentationO.value(),
+ {}, f, &errorMessage);
+ if (!errorMessage.isEmpty())
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ const Documentation documentation(detailed, {});
+ f->setDocumentation(documentation);
+}
+
+void QtDocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &e)
+{
+ auto te = e.typeEntry();
+ const QString sourceFileName =
+ findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include());
+ if (sourceFileName.isEmpty())
+ return;
+
+ QString errorMessage;
+ auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ return;
+ }
+ if (!extractEnumDocumentation(classDocumentationO.value(), e)) {
+ qCWarning(lcShibokenDoc, "%s",
+ qPrintable(msgCannotFindDocumentation(sourceFileName, {}, e, {})));
+ }
+}
+
+void QtDocParser::fillDocumentation(const AbstractMetaClassPtr &metaClass)
{
if (!metaClass)
return;
- const AbstractMetaClass* context = metaClass->enclosingClass();
- while(context) {
- if (context->enclosingClass() == nullptr)
+ auto context = metaClass->enclosingClass();
+ while (context) {
+ if (!context->enclosingClass())
break;
context = context->enclosingClass();
}
@@ -234,9 +292,9 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
+ metaClass->qualifiedCppName().toLower();
sourceFileRoot.replace(u"::"_s, u"-"_s);
- QFileInfo sourceFile(sourceFileRoot + QStringLiteral(".webxml"));
+ QFileInfo sourceFile(sourceFileRoot + webxmlSuffix);
if (!sourceFile.exists())
- sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml"));
+ sourceFile.setFile(sourceFileRoot + ".xml"_L1);
if (!sourceFile.exists()) {
qCWarning(lcShibokenDoc).noquote().nospace()
<< "Can't find qdoc file for class " << metaClass->name() << ", tried: "
@@ -247,22 +305,20 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
const QString sourceFileName = sourceFile.absoluteFilePath();
QString errorMessage;
- ClassDocumentation classDocumentation = parseWebXml(sourceFileName, &errorMessage);
- if (!classDocumentation) {
+ const auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
return;
}
- DocModificationList signedModifs, classModifs;
- const DocModificationList &mods = metaClass->typeEntry()->docModifications();
- for (const DocModification &docModif : mods) {
- if (docModif.signature().isEmpty())
- classModifs.append(docModif);
- else
- signedModifs.append(docModif);
+ const auto &classDocumentation = classDocumentationO.value();
+ for (const auto &p : classDocumentation.properties) {
+ Documentation doc(p.description, p.brief);
+ metaClass->setPropertyDocumentation(p.name, doc);
}
- QString docString = applyDocModifications(mods, classDocumentation.description);
+ QString docString = applyDocModifications(DocParser::getXpathDocModifications(metaClass),
+ classDocumentation.description);
if (docString.isEmpty()) {
QString className = metaClass->name();
@@ -281,12 +337,12 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
const auto &funcs = DocParser::documentableFunctions(metaClass);
for (const auto &func : funcs) {
const QString detailed =
- queryFunctionDocumentation(sourceFileName, classDocumentation,
- metaClass, func, signedModifs, &errorMessage);
+ functionDocumentation(sourceFileName, classDocumentation,
+ metaClass, func, &errorMessage);
if (!errorMessage.isEmpty())
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
const Documentation documentation(detailed, {});
- qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(documentation);
+ std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(documentation);
}
#if 0
// Fields
@@ -302,18 +358,35 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
#endif
// Enums
for (AbstractMetaEnum &meta_enum : metaClass->enums()) {
- Documentation enumDoc;
- const auto index = classDocumentation.indexOfEnum(meta_enum.name());
- if (index != -1) {
- enumDoc.setValue(classDocumentation.enums.at(index).description);
- meta_enum.setDocumentation(enumDoc);
- } else {
+ if (!extractEnumDocumentation(classDocumentation, meta_enum)) {
qCWarning(lcShibokenDoc, "%s",
qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, {})));
}
}
}
+bool QtDocParser::extractEnumDocumentation(const ClassDocumentation &classDocumentation,
+ AbstractMetaEnum &meta_enum)
+{
+ Documentation enumDoc;
+ const auto index = classDocumentation.indexOfEnum(meta_enum.name());
+ if (index == -1)
+ return false;
+ QString doc = classDocumentation.enums.at(index).description;
+ const auto firstPara = doc.indexOf(u"<para>");
+ if (firstPara != -1) {
+ const QString baseClass = QtDocParser::enumBaseClass(meta_enum);
+ if (baseClass != "Enum"_L1) {
+ const QString note = "(inherits <teletype>enum."_L1 + baseClass
+ + "</teletype>) "_L1;
+ doc.insert(firstPara + 6, note);
+ }
+ }
+ enumDoc.setValue(doc);
+ meta_enum.setDocumentation(enumDoc);
+ return true;
+}
+
static QString qmlReferenceLink(const QFileInfo &qmlModuleFi)
{
QString result;
diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.h b/sources/shiboken6/ApiExtractor/qtdocparser.h
index 2b82c1265..f6ba5e47a 100644
--- a/sources/shiboken6/ApiExtractor/qtdocparser.h
+++ b/sources/shiboken6/ApiExtractor/qtdocparser.h
@@ -12,23 +12,28 @@ class QtDocParser : public DocParser
{
public:
QtDocParser() = default;
- void fillDocumentation(AbstractMetaClass* metaClass) override;
+ void fillDocumentation(const AbstractMetaClassPtr &metaClass) override;
+ void fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f) override;
+ void fillGlobalEnumDocumentation(AbstractMetaEnum &e) override;
+
Documentation retrieveModuleDocumentation() override;
Documentation retrieveModuleDocumentation(const QString& name) override;
private:
- static QString queryFunctionDocumentation(const QString &sourceFileName,
- const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
- const AbstractMetaFunctionCPtr &func,
- const DocModificationList &signedModifs,
- QString *errorMessage);
+ static QString functionDocumentation(const QString &sourceFileName,
+ const ClassDocumentation &classDocumentation,
+ const AbstractMetaClassCPtr &metaClass,
+ const AbstractMetaFunctionCPtr &func,
+ QString *errorMessage);
static QString queryFunctionDocumentation(const QString &sourceFileName,
const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaFunctionCPtr &func,
QString *errorMessage);
+ static bool extractEnumDocumentation(const ClassDocumentation &classDocumentation,
+ AbstractMetaEnum &meta_enum);
+
};
#endif // QTDOCPARSER_H
diff --git a/sources/shiboken6/ApiExtractor/reporthandler.cpp b/sources/shiboken6/ApiExtractor/reporthandler.cpp
index 1fbd36bf4..23066ba21 100644
--- a/sources/shiboken6/ApiExtractor/reporthandler.cpp
+++ b/sources/shiboken6/ApiExtractor/reporthandler.cpp
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "reporthandler.h"
-#include "typesystem.h"
#include "typedatabase.h"
#include "qtcompat.h"
@@ -34,6 +33,7 @@ static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug;
static QSet<QString> m_reportedWarnings;
static QString m_prefix;
static bool m_withinProgress = false;
+static QByteArray m_progressMessage;
static int m_step_warning = 0;
static QElapsedTimer m_timer;
@@ -123,7 +123,7 @@ void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &cont
QString message = m_prefix;
if (!message.isEmpty())
message.append(u' ');
- const int prefixLength = message.size();
+ const auto prefixLength = message.size();
message.append(text);
// Replace file location tab by space
if (fileLocationPos >= 0)
@@ -148,9 +148,13 @@ void ReportHandler::startProgress(const QByteArray& str)
endProgress();
m_withinProgress = true;
- const auto ts = '[' + timeStamp() + ']';
- std::printf("%s %8s %-60s", qPrintable(m_prefix), ts.constData(), str.constData());
- std::fflush(stdout);
+ m_progressMessage = str;
+}
+
+static void indentStdout(qsizetype n)
+{
+ for (qsizetype i = 0; i < n; ++i)
+ fputc(' ', stdout);
}
void ReportHandler::endProgress()
@@ -159,11 +163,23 @@ void ReportHandler::endProgress()
return;
m_withinProgress = false;
+
+ std::fputs(m_prefix.toUtf8().constData(), stdout);
+ const auto ts = timeStamp();
+ if (ts.size() < 6)
+ indentStdout(6 - ts.size());
+ std::fputs(" [", stdout);
+ std::fputs(ts.constData(), stdout);
+ std::fputs("] ", stdout);
+ std::fputs(m_progressMessage.constData(), stdout);
+ if (m_progressMessage.size() < 60)
+ indentStdout(60 - m_progressMessage.size());
const char *endMessage = m_step_warning == 0
? "[" COLOR_GREEN "OK" COLOR_END "]\n"
: "[" COLOR_YELLOW "WARNING" COLOR_END "]\n";
std::fputs(endMessage, stdout);
std::fflush(stdout);
+ m_progressMessage.clear();
m_step_warning = 0;
}
diff --git a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
index d99c7ef8f..7b712fe35 100644
--- a/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
+++ b/sources/shiboken6/ApiExtractor/smartpointertypeentry.h
@@ -8,17 +8,23 @@
class SmartPointerTypeEntryPrivate;
+struct SmartPointerInstantiation
+{
+ QString name; // user defined name
+ TypeEntryCPtr typeEntry;
+};
+
class SmartPointerTypeEntry : public ComplexTypeEntry
{
public:
- using Instantiations = QList<const TypeEntry *>;
+ using Instantiations = QList<SmartPointerInstantiation>;
explicit SmartPointerTypeEntry(const QString &entryName,
const QString &getterName,
TypeSystem::SmartPointerType type,
const QString &refCountMethodName,
const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeSystem::SmartPointerType smartPointerType() const;
@@ -35,13 +41,11 @@ public:
TypeEntry *clone() const override;
- Instantiations instantiations() const;
+ const Instantiations &instantiations() const;
void setInstantiations(const Instantiations &i);
- bool matchesInstantiation(const TypeEntry *e) const;
+ bool matchesInstantiation(const TypeEntryCPtr &e) const;
- static QString getTargetFullName(const AbstractMetaType &metaType,
- bool includePackageName = true);
- static QString getTargetName(const AbstractMetaType &metaType);
+ QString getTargetName(const AbstractMetaType &metaType) const;
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
diff --git a/sources/shiboken6/ApiExtractor/templateargumententry.h b/sources/shiboken6/ApiExtractor/templateargumententry.h
index 6f191b595..9f2338022 100644
--- a/sources/shiboken6/ApiExtractor/templateargumententry.h
+++ b/sources/shiboken6/ApiExtractor/templateargumententry.h
@@ -12,7 +12,7 @@ class TemplateArgumentEntry : public TypeEntry
{
public:
explicit TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
int ordinal() const;
void setOrdinal(int o);
diff --git a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt
index 97ae0f850..76c014fbb 100644
--- a/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt
+++ b/sources/shiboken6/ApiExtractor/tests/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
set(CMAKE_AUTORCC ON)
macro(declare_test testname)
@@ -15,7 +18,7 @@ macro(declare_test testname)
${CMAKE_CURRENT_BINARY_DIR}
${apiextractor_SOURCE_DIR}
)
- target_link_libraries(${testname} PRIVATE apiextractor Qt${QT_MAJOR_VERSION}::Test)
+ target_link_libraries(${testname} PRIVATE apiextractor Qt::Test)
add_test(${testname} ${testname})
if (INSTALL_TESTS)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname}
diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp
index 17a6c5e2e..4b5da0c3a 100644
--- a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp
@@ -4,6 +4,7 @@
#include "testabstractmetaclass.h"
#include "abstractmetabuilder.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
#include <usingmember.h>
@@ -17,10 +18,12 @@ using namespace Qt::StringLiterals;
void TestAbstractMetaClass::testClassName()
{
- const char* cppCode ="class ClassName {};";
- const char* xmlCode = "<typesystem package=\"Foo\"><value-type name=\"ClassName\"/></typesystem>";
+ const char cppCode[] = "class ClassName {};";
+ const char xmlCode[] = R"(<typesystem package="Foo">
+ <value-type name="ClassName"/>
+</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
QCOMPARE(classes[0]->name(), u"ClassName");
@@ -28,15 +31,15 @@ void TestAbstractMetaClass::testClassName()
void TestAbstractMetaClass::testClassNameUnderNamespace()
{
- const char* cppCode ="namespace Namespace { class ClassName {}; }\n";
- const char* xmlCode = R"XML(
+ const char cppCode[] = "namespace Namespace { class ClassName {}; }\n";
+ const char xmlCode[] = R"XML(
<typesystem package="Foo">
<namespace-type name="Namespace">
<value-type name="ClassName"/>
</namespace-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2); // 1 namespace + 1 class
if (classes.constFirst()->name() != u"ClassName")
@@ -68,7 +71,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace()
// QVERIFY(classes[0]->hasNonPrivateConstructor());
}
-static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClass *c)
+static AbstractMetaFunctionCList virtualFunctions(const AbstractMetaClassCPtr &c)
{
AbstractMetaFunctionCList result;
const auto &functions = c->functions();
@@ -107,18 +110,16 @@ public:
</typesystem>
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 4);
- AbstractMetaClass* a = AbstractMetaClass::findClass(classes, u"A");
- AbstractMetaClass* b = AbstractMetaClass::findClass(classes, u"B");
- AbstractMetaClass* c = AbstractMetaClass::findClass(classes, u"C");
- const AbstractMetaClass *f = AbstractMetaClass::findClass(classes, u"F");
+ const auto a = AbstractMetaClass::findClass(classes, "A");
+ const auto b = AbstractMetaClass::findClass(classes, "B");
+ const auto c = AbstractMetaClass::findClass(classes, "C");
+ const auto f = AbstractMetaClass::findClass(classes, "F");
QVERIFY(f);
- AbstractMetaClass* no_class = nullptr;
-
- QCOMPARE(a->baseClass(), no_class);
+ QCOMPARE(a->baseClass(), nullptr);
QCOMPARE(b->baseClass(), a);
QCOMPARE(c->baseClass(), b);
QCOMPARE(f->baseClass(), c);
@@ -158,11 +159,11 @@ public:
const auto funcF = virtualFunctionsF.constFirst();
QCOMPARE(funcA->ownerClass(), a);
- QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::VirtualCppMethod));
+ QVERIFY(funcC->isVirtual());
QCOMPARE(funcB->ownerClass(), b);
QCOMPARE(funcC->ownerClass(), c);
- QVERIFY(funcC->attributes().testFlag(AbstractMetaFunction::OverriddenCppMethod));
- QVERIFY(funcF->attributes().testFlag(AbstractMetaFunction::FinalCppMethod));
+ QVERIFY(funcC->cppAttributes().testFlag(FunctionAttribute::Override));
+ QVERIFY(funcF->cppAttributes().testFlag(FunctionAttribute::Final));
QCOMPARE(funcA->declaringClass(), a);
QCOMPARE(funcB->declaringClass(), a);
@@ -193,34 +194,34 @@ class Derived : public Base {};
</typesystem>
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- auto base = AbstractMetaClass::findClass(classes, u"Base");
+ const auto base = AbstractMetaClass::findClass(classes, "Base");
QVERIFY(base);
QVERIFY(base->isPolymorphic());
- auto derived = AbstractMetaClass::findClass(classes, u"Derived");
+ const auto derived = AbstractMetaClass::findClass(classes, "Derived");
QVERIFY(derived);
QVERIFY(derived->isPolymorphic());
}
void TestAbstractMetaClass::testDefaultValues()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
class B {};\n\
void method(B b = B());\n\
};\n";
- const char* xmlCode = R"XML(
+ const char xmlCode[] = R"XML(
<typesystem package="Foo">
<value-type name='A'>
<value-type name='B'/>
</value-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
const auto candidates = classA->queryFunctionsByName(u"method"_s);
QCOMPARE(candidates.size(), 1);
const auto &method = candidates.constFirst();
@@ -230,12 +231,12 @@ void TestAbstractMetaClass::testDefaultValues()
void TestAbstractMetaClass::testModifiedDefaultValues()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
class B {};\n\
void method(B b = B());\n\
};\n";
- const char* xmlCode = R"XML(
+ const char xmlCode[] = R"XML(
<typesystem package="Foo">
<value-type name='A'>
<modify-function signature='method(A::B)'>
@@ -247,10 +248,10 @@ void TestAbstractMetaClass::testModifiedDefaultValues()
</value-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
const auto methodMatches = classA->queryFunctionsByName(u"method"_s);
QCOMPARE(methodMatches.size(), 1);
const auto method = methodMatches.constFirst();
@@ -261,25 +262,25 @@ void TestAbstractMetaClass::testModifiedDefaultValues()
void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
class B {};\n\
virtual void method();\n\
};\n";
- const char* xmlCode = R"XML(
+ const char xmlCode[] = R"XML(
<typesystem package="Foo">
<object-type name='A'>
<value-type name='B'/>
</object-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QVERIFY(classA->isPolymorphic());
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B");
+ const auto classB = AbstractMetaClass::findClass(classes, "A::B");
QVERIFY(classB);
QVERIFY(!classB->isPolymorphic());
}
@@ -301,15 +302,15 @@ void TestAbstractMetaClass::testForwardDeclaredInnerClass()
</value-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"A::B");
+ const auto classB = AbstractMetaClass::findClass(classes, "A::B");
QVERIFY(classB);
- const auto fooF = classB->findFunction(u"foo");
- QVERIFY(!fooF.isNull());
+ const auto fooF = classB->findFunction("foo");
+ QVERIFY(fooF);
}
void TestAbstractMetaClass::testSpecialFunctions()
@@ -332,11 +333,11 @@ void TestAbstractMetaClass::testSpecialFunctions()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor);
QCOMPARE(ctors.size(), 2);
@@ -347,7 +348,7 @@ void TestAbstractMetaClass::testSpecialFunctions()
QCOMPARE(assigmentOps.constFirst()->functionType(),
AbstractMetaFunction::AssignmentOperatorFunction);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
ctors = classB->queryFunctions(FunctionQueryOption::AnyConstructor);
QCOMPARE(ctors.size(), 2);
@@ -360,7 +361,7 @@ void TestAbstractMetaClass::testSpecialFunctions()
void TestAbstractMetaClass::testClassDefaultConstructors()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
\n\
struct B {\n\
@@ -386,7 +387,7 @@ void TestAbstractMetaClass::testClassDefaultConstructors()
struct F {\n\
F(int, int);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<value-type name='A'/>\n\
@@ -398,11 +399,11 @@ void TestAbstractMetaClass::testClassDefaultConstructors()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 6);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->functions().size(), 2);
@@ -416,28 +417,28 @@ void TestAbstractMetaClass::testClassDefaultConstructors()
QCOMPARE(ctors[1]->arguments().size(), 1);
QCOMPARE(ctors[1]->minimalSignature(), u"A(A)");
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
QCOMPARE(classB->functions().size(), 2);
QCOMPARE(classB->functions().constFirst()->minimalSignature(), u"B()");
- AbstractMetaClass* classC = AbstractMetaClass::findClass(classes, u"C");
+ const auto classC = AbstractMetaClass::findClass(classes, "C");
QVERIFY(classC);
QCOMPARE(classC->functions().size(), 1);
QCOMPARE(classC->functions().constFirst()->minimalSignature(), u"C(C)");
- AbstractMetaClass* classD = AbstractMetaClass::findClass(classes, u"D");
+ const auto classD = AbstractMetaClass::findClass(classes, "D");
QVERIFY(classD);
QCOMPARE(classD->functions().size(), 1);
QCOMPARE(classD->functions().constFirst()->minimalSignature(), u"D(D)");
QVERIFY(classD->functions().constFirst()->isPrivate());
- AbstractMetaClass* classE = AbstractMetaClass::findClass(classes, u"E");
+ const auto classE = AbstractMetaClass::findClass(classes, "E");
QVERIFY(classE);
QVERIFY(classE->hasPrivateDestructor());
QCOMPARE(classE->functions().size(), 0);
- AbstractMetaClass* classF = AbstractMetaClass::findClass(classes, u"F");
+ const auto classF = AbstractMetaClass::findClass(classes, "F");
QVERIFY(classF);
ctors = classF->queryFunctions(FunctionQueryOption::AnyConstructor);
@@ -453,24 +454,24 @@ void TestAbstractMetaClass::testClassDefaultConstructors()
void TestAbstractMetaClass::testClassInheritedDefaultConstructors()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
A();\n\
private: \n\
A(const A&);\n\
};\n\
struct B : public A {};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<object-type name='A'/>\n\
<object-type name='B'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
auto ctors = classA->queryFunctions(FunctionQueryOption::AnyConstructor);
@@ -484,7 +485,7 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors()
QCOMPARE(ctors[1]->minimalSignature(), u"A(A)");
QVERIFY(ctors[1]->isPrivate());
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
ctors = classB->queryFunctions(FunctionQueryOption::Constructors);
@@ -495,20 +496,20 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors()
void TestAbstractMetaClass::testAbstractClassDefaultConstructors()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
virtual void method() = 0;\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<object-type name='A'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors);
@@ -519,17 +520,17 @@ void TestAbstractMetaClass::testAbstractClassDefaultConstructors()
void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors()
{
- const char* cppCode ="struct A {};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A {};\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<object-type name='A'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
const auto ctors = classA->queryFunctions(FunctionQueryOption::Constructors);
@@ -540,7 +541,7 @@ void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors()
void TestAbstractMetaClass::testIsPolymorphic()
{
- const char* cppCode = "\
+ const char cppCode[] = "\
class A\n\
{\n\
public:\n\
@@ -554,7 +555,7 @@ void TestAbstractMetaClass::testIsPolymorphic()
B();\n\
inline bool abc() const { return false; }\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='bool'/>\n\
<value-type name='A'/>\n\
@@ -562,13 +563,13 @@ void TestAbstractMetaClass::testIsPolymorphic()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- AbstractMetaClass* b = AbstractMetaClass::findClass(classes, u"A");
+ const auto b = AbstractMetaClass::findClass(classes, "A");
QVERIFY(!b->isPolymorphic());
- AbstractMetaClass* a = AbstractMetaClass::findClass(classes, u"B");
+ const auto a = AbstractMetaClass::findClass(classes, "B");
QVERIFY(!a->isPolymorphic());
}
@@ -592,12 +593,12 @@ class Derived : public BaseAlias2 {
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto base = AbstractMetaClass::findClass(classes, u"Base");
+ const auto base = AbstractMetaClass::findClass(classes, "Base");
QVERIFY(base);
- auto derived = AbstractMetaClass::findClass(classes, u"Derived");
+ const auto derived = AbstractMetaClass::findClass(classes, "Derived");
QVERIFY(derived);
QCOMPARE(derived->baseClasses().value(0), base);
}
@@ -643,7 +644,7 @@ void TestAbstractMetaClass::testFreeOperators()
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const auto classes = builder->classes();
QCOMPARE(classes.size(), 1);
QVERIFY(classes.constFirst()->hasArithmeticOperatorOverload());
@@ -677,12 +678,12 @@ public:
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto base = AbstractMetaClass::findClass(classes, u"Base");
+ const auto base = AbstractMetaClass::findClass(classes, "Base");
QVERIFY(base);
- auto derived = AbstractMetaClass::findClass(classes, u"Derived");
+ const auto derived = AbstractMetaClass::findClass(classes, "Derived");
QVERIFY(derived);
const auto usingMembers = derived->usingMembers();
QCOMPARE(usingMembers.size(), 2);
@@ -732,9 +733,9 @@ void TestAbstractMetaClass::testUsingTemplateMembers()
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(code.constData(), xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- auto valueList = AbstractMetaClass::findClass(classes, u"ValueList");
+ const auto valueList = AbstractMetaClass::findClass(classes, "ValueList");
QVERIFY(valueList);
auto list = valueList->templateBaseClass();
QVERIFY(valueList->isUsingMember(list, u"append"_s, Access::Public));
@@ -762,9 +763,9 @@ public:
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- auto *tc = AbstractMetaClass::findClass(classes, u"TestClass");
+ const auto tc = AbstractMetaClass::findClass(classes, "TestClass");
// Verify that the constructor and 2 functions are generated.
const auto &functions = tc->functions();
QCOMPARE(functions.size(), 5);
diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp
index 0b210583f..2c320c874 100644
--- a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp
@@ -3,8 +3,10 @@
#include "testabstractmetatype.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <typesystem.h>
#include <parser/codemodel.h>
#include <typeparser.h>
@@ -46,13 +48,13 @@ void TestAbstractMetaType::parsing()
void TestAbstractMetaType::testConstCharPtrType()
{
- const char* cppCode ="const char* justAtest();\n";
- const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ const char cppCode[] = "const char* justAtest();\n";
+ const char xmlCode[] = "<typesystem package=\"Foo\">\n\
<primitive-type name='char'/>\n\
<function signature='justAtest()' />\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->globalFunctions().size(), 1);
const auto func = builder->globalFunctions().constFirst();
AbstractMetaType rtype = func->type();
@@ -73,9 +75,9 @@ void TestAbstractMetaType::testConstCharPtrType()
void TestAbstractMetaType::testApiVersionSupported()
{
- const char* cppCode ="class foo {}; class foo2 {};\n\
+ const char cppCode[] = "class foo {}; class foo2 {};\n\
void justAtest(); void justAtest3();\n";
- const char* xmlCode = "<typesystem package='Foo'>\n\
+ const char xmlCode[] = "<typesystem package='Foo'>\n\
<value-type name='foo' since='0.1'/>\n\
<value-type name='foo2' since='1.0'/>\n\
<value-type name='foo3' since='1.1'/>\n\
@@ -85,7 +87,7 @@ void TestAbstractMetaType::testApiVersionSupported()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
false, u"1.0"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
@@ -97,13 +99,13 @@ void TestAbstractMetaType::testApiVersionSupported()
void TestAbstractMetaType::testApiVersionNotSupported()
{
- const char* cppCode ="class object {};\n";
- const char* xmlCode = "<typesystem package='Foo'>\n\
+ const char cppCode[] = "class object {};\n";
+ const char xmlCode[] = "<typesystem package='Foo'>\n\
<value-type name='object' since='0.1'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
true, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
@@ -111,14 +113,14 @@ void TestAbstractMetaType::testApiVersionNotSupported()
void TestAbstractMetaType::testCharType()
{
- const char* cppCode ="char justAtest(); class A {};\n";
- const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ const char cppCode[] = "char justAtest(); class A {};\n";
+ const char xmlCode[] = "<typesystem package=\"Foo\">\n\
<primitive-type name='char'/>\n\
<value-type name='A'/>\n\
<function signature='justAtest()'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
@@ -145,28 +147,28 @@ void TestAbstractMetaType::testCharType()
void TestAbstractMetaType::testTypedef()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
void someMethod();\n\
};\n\
typedef A B;\n\
typedef B C;\n";
- const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ const char xmlCode[] = "<typesystem package=\"Foo\">\n\
<value-type name='C' />\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- const AbstractMetaClass *c = AbstractMetaClass::findClass(classes, u"C");
+ const auto c = AbstractMetaClass::findClass(classes, "C");
QVERIFY(c);
QVERIFY(c->isTypeDef());
}
void TestAbstractMetaType::testTypedefWithTemplates()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
template<typename T>\n\
class A {};\n\
\n\
@@ -174,13 +176,13 @@ void TestAbstractMetaType::testTypedefWithTemplates()
typedef A<B> C;\n\
\n\
void func(C c);\n";
- const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ const char xmlCode[] = "<typesystem package=\"Foo\">\n\
<container-type name='A' type='list'/>\n\
<value-type name='B' />\n\
<function signature='func(A&lt;B&gt;)'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
@@ -191,25 +193,25 @@ void TestAbstractMetaType::testTypedefWithTemplates()
QCOMPARE(args.size(), 1);
const AbstractMetaArgument &arg = args.constFirst();
AbstractMetaType metaType = arg.type();
- QCOMPARE(metaType.cppSignature(), u"A<B >");
+ QCOMPARE(metaType.cppSignature(), u"A<B>");
}
void TestAbstractMetaType::testObjectTypeUsedAsValue()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class A {\n\
void method(A);\n\
};\n";
- const char* xmlCode = "<typesystem package='Foo'>\n\
+ const char xmlCode[] = "<typesystem package='Foo'>\n\
<object-type name='A'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
const auto overloads = classA->queryFunctionsByName(u"method"_s);
QCOMPARE(overloads.size(), 1);
diff --git a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp
index d1aa1a7c4..a891e1e28 100644
--- a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp
@@ -3,11 +3,13 @@
#include "testaddfunction.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <codesnip.h>
-#include <modifications.h>
-#include <modifications_p.h>
+#include <addedfunction.h>
+#include <addedfunction_p.h>
#include <complextypeentry.h>
#include <primitivetypeentry.h>
@@ -17,28 +19,31 @@
using namespace Qt::StringLiterals;
+static constexpr auto voidT = "void"_L1;
+
void TestAddFunction::testParsingFuncNameAndConstness()
{
// generic test...
- const char sig1[] = "func(type1, const type2, const type3* const)";
+ static constexpr auto sig1 = "func(type1, const type2, const type3* const)"_L1;
QString errorMessage;
- auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s,
- &errorMessage);
- QVERIFY2(!f1.isNull(), qPrintable(errorMessage));
+ auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage);
+ QVERIFY2(f1, qPrintable(errorMessage));
QCOMPARE(f1->name(), u"func");
QCOMPARE(f1->arguments().size(), 3);
TypeInfo retval = f1->returnType();
- QCOMPARE(retval.qualifiedName(), QStringList{u"void"_s});
+ QCOMPARE(retval.qualifiedName(), QStringList{voidT});
QCOMPARE(retval.indirections(), 0);
QCOMPARE(retval.isConstant(), false);
QCOMPARE(retval.referenceType(), NoReference);
// test with a ugly template as argument and other ugly stuff
- const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *@my_name@, const type3* const ) const ";
- auto f2 = AddedFunction::createAddedFunction(QLatin1StringView(sig2),
+ static constexpr auto sig2 =
+ " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * >"
+ " * *@my_name@, const type3* const ) const "_L1;
+ auto f2 = AddedFunction::createAddedFunction(sig2,
u"const Abc<int& , C<char*> * > * *"_s,
&errorMessage);
- QVERIFY2(!f2.isNull(), qPrintable(errorMessage));
+ QVERIFY2(f2, qPrintable(errorMessage));
QCOMPARE(f2->name(), u"_fu__nc_");
const auto &args = f2->arguments();
QCOMPARE(args.size(), 4);
@@ -64,18 +69,15 @@ void TestAddFunction::testParsingFuncNameAndConstness()
QVERIFY(args.at(3).name.isEmpty());
// function with no args.
- const char sig3[] = "func()";
- auto f3 = AddedFunction::createAddedFunction(QLatin1StringView(sig3), u"void"_s,
- &errorMessage);
- QVERIFY2(!f3.isNull(), qPrintable(errorMessage));
+ auto f3 = AddedFunction::createAddedFunction("func()"_L1, voidT, &errorMessage);
+ QVERIFY2(f3, qPrintable(errorMessage));
QCOMPARE(f3->name(), u"func");
QCOMPARE(f3->arguments().size(), 0);
// const call operator
- const char sig4[] = "operator()(int)const";
- auto f4 = AddedFunction::createAddedFunction(QLatin1StringView(sig4), u"int"_s,
- &errorMessage);
- QVERIFY2(!f4.isNull(), qPrintable(errorMessage));
+ auto f4 = AddedFunction::createAddedFunction("operator()(int)const"_L1,
+ "int"_L1, &errorMessage);
+ QVERIFY2(f4, qPrintable(errorMessage));
QCOMPARE(f4->name(), u"operator()");
QCOMPARE(f4->arguments().size(), 1);
QVERIFY(f4->isConstant());
@@ -100,15 +102,15 @@ struct A {
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
- TypeDatabase* typeDb = TypeDatabase::instance();
+ QVERIFY(builder);
+ auto *typeDb = TypeDatabase::instance();
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
// default ctor, default copy ctor, func a() and the added functions
QCOMPARE(classA->functions().size(), 5);
- auto addedFunc = classA->findFunction(u"b");
+ auto addedFunc = classA->findFunction("b");
QVERIFY(addedFunc);
QCOMPARE(addedFunc->access(), Access::Protected);
QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction);
@@ -129,7 +131,7 @@ struct A {
QCOMPARE(args.at(1).defaultValueExpression(), u"4.6");
QCOMPARE(args.at(2).type().typeEntry(), typeDb->findType(u"B"_s));
- auto addedCallOperator = classA->findFunction(u"operator()");
+ auto addedCallOperator = classA->findFunction("operator()");
QVERIFY(addedCallOperator);
}
@@ -144,9 +146,9 @@ void TestAddFunction::testAddFunctionConstructor()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->functions().size(), 3); // default and added ctors
const auto addedFunc = classA->functions().constLast();
@@ -167,9 +169,9 @@ void TestAddFunction::testAddFunctionTagDefaultValues()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
// default ctor, default copy ctor and the added function
QCOMPARE(classA->functions().size(), 3);
@@ -193,9 +195,9 @@ void TestAddFunction::testAddFunctionCodeSnippets()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
const auto addedFunc = classA->functions().constLast();
QVERIFY(addedFunc->hasInjectedCode());
@@ -203,11 +205,10 @@ void TestAddFunction::testAddFunctionCodeSnippets()
void TestAddFunction::testAddFunctionWithoutParenteses()
{
- const char sig1[] = "func";
+ static constexpr auto sig1 = "func"_L1;
QString errorMessage;
- auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s,
- &errorMessage);
- QVERIFY2(!f1.isNull(), qPrintable(errorMessage));
+ auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage);
+ QVERIFY2(f1, qPrintable(errorMessage));
QCOMPARE(f1->name(), u"func");
QCOMPARE(f1->arguments().size(), 0);
QCOMPARE(f1->isConstant(), false);
@@ -223,12 +224,12 @@ void TestAddFunction::testAddFunctionWithoutParenteses()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"func");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction(sig1);
+ QVERIFY(addedFunc);
QVERIFY(addedFunc->hasInjectedCode());
const auto snips = addedFunc->injectedCodeSnips(TypeSystem::CodeSnipPositionAny,
TypeSystem::TargetLangCode);
@@ -237,11 +238,10 @@ void TestAddFunction::testAddFunctionWithoutParenteses()
void TestAddFunction::testAddFunctionWithDefaultArgs()
{
- const char sig1[] = "func";
+ static constexpr auto sig1 = "func"_L1;
QString errorMessage;
- auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s,
- &errorMessage);
- QVERIFY2(!f1.isNull(), qPrintable(errorMessage));
+ auto f1 = AddedFunction::createAddedFunction(sig1, voidT, &errorMessage);
+ QVERIFY2(f1, qPrintable(errorMessage));
QCOMPARE(f1->name(), u"func");
QCOMPARE(f1->arguments().size(), 0);
QCOMPARE(f1->isConstant(), false);
@@ -260,12 +260,12 @@ void TestAddFunction::testAddFunctionWithDefaultArgs()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"func");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction(sig1);
+ QVERIFY(addedFunc);
const AbstractMetaArgument &arg = addedFunc->arguments().at(1);
QCOMPARE(arg.defaultValueExpression(), u"2");
}
@@ -283,18 +283,18 @@ void TestAddFunction::testAddFunctionAtModuleLevel()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- TypeDatabase* typeDb = TypeDatabase::instance();
+ auto *typeDb = TypeDatabase::instance();
AddedFunctionList addedFuncs = typeDb->findGlobalUserFunctions(u"func"_s);
QCOMPARE(addedFuncs.size(), 1);
- const FunctionModificationList mods = addedFuncs.constFirst()->modifications;
+ auto &mods = addedFuncs.constFirst()->modifications();
QCOMPARE(mods.size(), 1);
QVERIFY(mods.constFirst().isCodeInjection());
@@ -304,11 +304,10 @@ void TestAddFunction::testAddFunctionAtModuleLevel()
void TestAddFunction::testAddFunctionWithVarargs()
{
- const char sig1[] = "func(int,char,...)";
QString errorMessage;
- auto f1 = AddedFunction::createAddedFunction(QLatin1StringView(sig1), u"void"_s,
+ auto f1 = AddedFunction::createAddedFunction("func(int,char,...)"_L1, voidT,
&errorMessage);
- QVERIFY2(!f1.isNull(), qPrintable(errorMessage));
+ QVERIFY2(f1, qPrintable(errorMessage));
QCOMPARE(f1->name(), u"func");
QCOMPARE(f1->arguments().size(), 3);
QVERIFY(!f1->isConstant());
@@ -324,12 +323,12 @@ void TestAddFunction::testAddFunctionWithVarargs()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"func");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction("func");
+ QVERIFY(addedFunc);
const AbstractMetaArgument &arg = addedFunc->arguments().constLast();
QVERIFY(arg.type().isVarargs());
QVERIFY(arg.type().typeEntry()->isVarargs());
@@ -348,12 +347,12 @@ void TestAddFunction::testAddStaticFunction()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"func");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction("func");
+ QVERIFY(addedFunc);
QVERIFY(addedFunc->isStatic());
}
@@ -373,13 +372,13 @@ void TestAddFunction::testAddGlobalFunction()
<value-type name='B'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const auto globalFuncs = builder->globalFunctions();
QCOMPARE(globalFuncs.size(), 2);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(builder->classes(), u"B");
+ const auto classB = AbstractMetaClass::findClass(builder->classes(), "B");
QVERIFY(classB);
- QVERIFY(!classB->findFunction(u"globalFunc"));
- QVERIFY(!classB->findFunction(u"globalFunc2"));
+ QVERIFY(!classB->findFunction("globalFunc"));
+ QVERIFY(!classB->findFunction("globalFunc2"));
QVERIFY(!globalFuncs[0]->injectedCodeSnips().isEmpty());
QVERIFY(!globalFuncs[1]->injectedCodeSnips().isEmpty());
}
@@ -399,7 +398,7 @@ void TestAddFunction::testAddFunctionWithApiVersion()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
true, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const auto globalFuncs = builder->globalFunctions();
QCOMPARE(globalFuncs.size(), 1);
}
@@ -422,11 +421,11 @@ void TestAddFunction::testModifyAddedFunction()
</typesystem>
)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, u"Foo");
- const auto method = foo->findFunction(u"method");
- QVERIFY(!method.isNull());
+ const auto foo = AbstractMetaClass::findClass(classes, "Foo");
+ const auto method = foo->findFunction("method");
+ QVERIFY(method);
QCOMPARE(method->arguments().size(), 2);
const AbstractMetaArgument &arg = method->arguments().at(1);
QCOMPARE(arg.defaultValueExpression(), u"0");
@@ -449,17 +448,17 @@ void TestAddFunction::testAddFunctionOnTypedef()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, u"FooInt");
+ const auto foo = AbstractMetaClass::findClass(classes, "FooInt");
QVERIFY(foo);
QVERIFY(foo->hasNonPrivateConstructor());
const auto &lst = foo->queryFunctions(FunctionQueryOption::AnyConstructor);
for (const auto &f : lst)
QVERIFY(f->signature().startsWith(f->name()));
QCOMPARE(lst.size(), 2);
- const auto method = foo->findFunction(u"method");
- QVERIFY(!method.isNull());
+ const auto method = foo->findFunction("method");
+ QVERIFY(method);
}
void TestAddFunction::testAddFunctionWithTemplateArg()
@@ -473,7 +472,7 @@ void TestAddFunction::testAddFunctionWithTemplateArg()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->globalFunctions().size(), 1);
const auto func = builder->globalFunctions().constFirst();
const AbstractMetaArgument &arg = func->arguments().constFirst();
diff --git a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp
index 0afbcb38f..6e1820bed 100644
--- a/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testarrayargument.cpp
@@ -3,9 +3,11 @@
#include "testarrayargument.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetaenum.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <primitivetypeentry.h>
#include <parser/enumvalue.h>
@@ -17,12 +19,12 @@ using namespace Qt::StringLiterals;
void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
enum SomeEnum { Value0, Value1, NValues };\n\
void method(double[3]);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='double'/>\n\
<object-type name='A'>\n\
@@ -32,7 +34,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
const AbstractMetaArgument &arg = classA->functions().constLast()->arguments().constFirst();
@@ -41,10 +43,10 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger()
QCOMPARE(arg.type().arrayElementType()->name(), u"double");
}
-static QString functionMinimalSignature(const AbstractMetaClass *c, const QString &name)
+static QString functionMinimalSignature(const AbstractMetaClassCPtr &c, const QString &name)
{
const auto f = c->findFunction(name);
- return f.isNull() ? QString() : f->minimalSignature();
+ return f ? f->minimalSignature() : QString();
}
void TestArrayArgument::testArraySignature()
@@ -70,7 +72,7 @@ void TestArrayArgument::testArraySignature()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QCOMPARE(functionMinimalSignature(classA, u"mi1"_s),
u"mi1(int[5])");
QCOMPARE(functionMinimalSignature(classA, u"mi1c"_s),
@@ -91,12 +93,12 @@ void TestArrayArgument::testArraySignature()
void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
enum SomeEnum { Value0, Value1, NValues };\n\
void method(double[NValues]);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='double'/>\n\
<object-type name='A'>\n\
@@ -106,7 +108,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
- AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
auto someEnum = classA->findEnum(u"SomeEnum"_s);
@@ -122,12 +124,12 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue()
void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
enum SomeEnum { Value0, Value1, NValues };\n\
struct A {\n\
void method(double[NValues]);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='double'/>\n\
<enum-type name='SomeEnum'/>\n\
@@ -136,8 +138,8 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnu
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ QVERIFY(builder);
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
AbstractMetaEnum someEnum = builder->globalEnums().constFirst();
diff --git a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp
index c6c209bb4..4829e6c33 100644
--- a/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testcodeinjection.cpp
@@ -8,6 +8,7 @@
#include <modifications.h>
#include <textstream.h>
#include <complextypeentry.h>
+#include <valuetypeentry.h>
#include <qtcompat.h>
@@ -40,7 +41,7 @@ void TestCodeInjections::testReadFile()
QFETCH(QString, snippet);
QFETCH(QString, expected);
- const char* cppCode ="struct A {};\n";
+ const char cppCode[] = "struct A {};\n";
int argc = 0;
char *argv[] = {nullptr};
QCoreApplication app(argc, argv);
@@ -58,20 +59,22 @@ void TestCodeInjections::testReadFile()
</value-type>\n\
</typesystem>\n"_s;
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().constData()));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QCOMPARE(classA->typeEntry()->codeSnips().size(), 1);
QString code = classA->typeEntry()->codeSnips().constFirst().code();
QVERIFY(code.indexOf(expected) != -1);
- code = classA->typeEntry()->targetConversionRule();
+ QVERIFY(classA->typeEntry()->isValue());
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry());
+ code = vte->targetConversionRule();
QVERIFY(code.indexOf(expected) != -1);
}
void TestCodeInjections::testInjectWithValidApiVersion()
{
- const char* cppCode ="struct A {};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A {};\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<value-type name='A'>\n\
<inject-code class='target' since='1.0'>\n\
@@ -82,16 +85,16 @@ void TestCodeInjections::testInjectWithValidApiVersion()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
true, u"1.0"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QCOMPARE(classA->typeEntry()->codeSnips().size(), 1);
}
void TestCodeInjections::testInjectWithInvalidApiVersion()
{
- const char* cppCode ="struct A {};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A {};\n";
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<value-type name='A'>\n\
<inject-code class='target' since='1.0'>\n\
@@ -102,30 +105,27 @@ void TestCodeInjections::testInjectWithInvalidApiVersion()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
true, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QCOMPARE(classA->typeEntry()->codeSnips().size(), 0);
}
void TestCodeInjections::testTextStream()
{
StringStream str(TextStream::Language::Cpp);
- str << "void foo(int a, int b) {\n";
- {
- Indentation i(str);
- str << "if (a == b)\n" << indent << "return a;\n" << outdent
- << "#if Q_OS_WIN\nprint()\n#endif\nreturn a + b;\n";
- }
- str << "}\n\n// A table\n|"
+ str << "void foo(int a, int b) {\n" << indent
+ << "if (a == b)\n" << indent << "return a;\n" << outdent
+ << "#if Q_OS_WIN\nprint()\n#endif\nreturn a + b;\n" << outdent
+ << "}\n\n// A table\n|"
<< AlignedField("bla", 40, QTextStream::AlignRight) << "|\n|"
<< AlignedField("bla", 40, QTextStream::AlignLeft) << "|\n|"
<< AlignedField(QString(), 40, QTextStream::AlignLeft) << "|\n";
str << "\n2nd table\n|" << AlignedField("bla", 3, QTextStream::AlignLeft)
<< '|' << AlignedField(QString{}, 0, QTextStream::AlignLeft) << "|\n";
-static const char expected[] = R"(void foo(int a, int b) {
+constexpr auto expected = R"(void foo(int a, int b) {
if (a == b)
return a;
#if Q_OS_WIN
@@ -141,9 +141,9 @@ static const char expected[] = R"(void foo(int a, int b) {
2nd table
|bla||
-)";
+)"_L1;
- QCOMPARE(str.toString(), QLatin1String(expected));
+ QCOMPARE(str.toString(), expected);
}
void TestCodeInjections::testTextStreamRst()
diff --git a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp
index 164409578..0bb72b3c1 100644
--- a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp
@@ -11,7 +11,7 @@
void TestContainer::testContainerType()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
namespace std {\n\
template<class T>\n\
class list {\n\
@@ -20,7 +20,7 @@ void TestContainer::testContainerType()
}\n\
class A : public std::list<int> {\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='std' generate='no' />\n\
<container-type name='std::list' type='list' />\n\
@@ -28,21 +28,21 @@ void TestContainer::testContainerType()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
//search for class A
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
auto baseContainer = classA->typeEntry()->baseContainerType();
QVERIFY(baseContainer);
- QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(),
+ QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(),
ContainerTypeEntry::ListContainer);
}
void TestContainer::testListOfValueType()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
namespace std {\n\
template<class T>\n\
class list {\n\
@@ -52,7 +52,7 @@ void TestContainer::testListOfValueType()
class ValueType {};\n\
class A : public std::list<ValueType> {\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='std' generate='no'/>\n\
<container-type name='std::list' type='list'/>\n\
@@ -61,11 +61,11 @@ void TestContainer::testListOfValueType()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->templateBaseClassInstantiations().size(), 1);
const AbstractMetaType templateInstanceType =
diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp
index a03220b0a..8f2b277af 100644
--- a/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testconversionoperator.cpp
@@ -5,6 +5,7 @@
#include "testutil.h"
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <typesystem.h>
#include <qtcompat.h>
@@ -32,11 +33,11 @@ void TestConversionOperator::testConversionOperator()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
- const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ const auto classC = AbstractMetaClass::findClass(classes, "C");
QVERIFY(classA);
QVERIFY(classB);
QVERIFY(classC);
@@ -52,7 +53,7 @@ void TestConversionOperator::testConversionOperator()
break;
}
}
- QVERIFY(!convOp.isNull());
+ QVERIFY(convOp);
QVERIFY(classA->externalConversionOperators().contains(convOp));
}
@@ -70,9 +71,9 @@ void TestConversionOperator::testConversionOperatorOfDiscardedClass()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->externalConversionOperators().size(), 0);
}
@@ -94,10 +95,10 @@ void TestConversionOperator::testRemovedConversionOperator()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classA);
QVERIFY(classB);
QCOMPARE(classA->functions().size(), 2);
@@ -120,10 +121,10 @@ void TestConversionOperator::testConversionOperatorReturningReference()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classA);
QVERIFY(classB);
QCOMPARE(classA->functions().size(), 2);
@@ -154,10 +155,10 @@ void TestConversionOperator::testConversionOperatorReturningConstReference()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classA);
QVERIFY(classB);
QCOMPARE(classA->functions().size(), 2);
diff --git a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp
index 5f126c5f5..b5efd92a6 100644
--- a/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testconversionruletag.cpp
@@ -7,6 +7,7 @@
#include <complextypeentry.h>
#include <customconversion.h>
#include <primitivetypeentry.h>
+#include <valuetypeentry.h>
#include <qtcompat.h>
@@ -20,10 +21,10 @@ void TestConversionRuleTag::testConversionRuleTagWithFile()
{
// FIXME PYSIDE7 remove
// temp file used later
- const char conversionData[] = "Hi! I'm a conversion rule.";
+ constexpr auto conversionData = "Hi! I'm a conversion rule."_L1;
QTemporaryFile file;
- file.open();
- QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1));
+ QVERIFY(file.open());
+ QCOMPARE(file.write(conversionData.constData()), conversionData.size());
file.close();
const char cppCode[] = "struct A {};\n";
@@ -34,13 +35,15 @@ void TestConversionRuleTag::testConversionRuleTagWithFile()
</value-type>\n\
</typesystem>\n"_s;
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data()));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const ComplexTypeEntry* typeEntry = classA->typeEntry();
- QVERIFY(typeEntry->hasTargetConversionRule());
- QCOMPARE(typeEntry->targetConversionRule(), QLatin1String(conversionData));
+ const auto typeEntry = classA->typeEntry();
+ QVERIFY(typeEntry->isValue());
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry);
+ QVERIFY(vte->hasTargetConversionRule());
+ QCOMPARE(vte->targetConversionRule(), conversionData);
}
void TestConversionRuleTag::testConversionRuleTagReplace()
@@ -53,7 +56,7 @@ void TestConversionRuleTag::testConversionRuleTagReplace()
struct B {\n\
A createA();\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<primitive-type name='char'/>\n\
@@ -82,13 +85,13 @@ void TestConversionRuleTag::testConversionRuleTagReplace()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
- TypeDatabase* typeDb = TypeDatabase::instance();
- PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s);
+ QVERIFY(builder);
+ auto *typeDb = TypeDatabase::instance();
+ auto typeA = typeDb->findPrimitiveType(u"A"_s);
QVERIFY(typeA);
- CustomConversion* conversion = typeA->customConversion();
- QVERIFY(conversion);
+ QVERIFY(typeA->hasCustomConversion());
+ auto conversion = typeA->customConversion();
QCOMPARE(typeA, conversion->ownerType());
QCOMPARE(conversion->nativeToTargetConversion().simplified(),
@@ -98,32 +101,33 @@ void TestConversionRuleTag::testConversionRuleTagReplace()
QVERIFY(conversion->hasTargetToNativeConversions());
QCOMPARE(conversion->targetToNativeConversions().size(), 3);
- CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().at(0);
- QVERIFY(toNative);
- QCOMPARE(toNative->sourceTypeName(), u"TargetNone");
- QVERIFY(toNative->isCustomType());
- QCOMPARE(toNative->sourceType(), nullptr);
- QCOMPARE(toNative->sourceTypeCheck(), u"%IN == Target_None");
- QCOMPARE(toNative->conversion().simplified(),
+ QVERIFY(!conversion->targetToNativeConversions().isEmpty());
+ auto toNative = conversion->targetToNativeConversions().at(0);
+ QCOMPARE(toNative.sourceTypeName(), u"TargetNone");
+ QVERIFY(toNative.isCustomType());
+ QCOMPARE(toNative.sourceType(), nullptr);
+ QCOMPARE(toNative.sourceTypeCheck(), u"%IN == Target_None");
+ QCOMPARE(toNative.conversion().simplified(),
u"DoThat(); DoSomething(); %OUT = A();");
+ QVERIFY(conversion->targetToNativeConversions().size() > 1);
toNative = conversion->targetToNativeConversions().at(1);
- QVERIFY(toNative);
- QCOMPARE(toNative->sourceTypeName(), u"B");
- QVERIFY(!toNative->isCustomType());
- TypeEntry* typeB = typeDb->findType(u"B"_s);
+ QCOMPARE(toNative.sourceTypeName(), u"B");
+ QVERIFY(!toNative.isCustomType());
+ auto typeB = typeDb->findType(u"B"_s);
QVERIFY(typeB);
- QCOMPARE(toNative->sourceType(), typeB);
- QCOMPARE(toNative->sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)");
- QCOMPARE(toNative->conversion().trimmed(), u"%OUT = %IN.createA();");
+ QCOMPARE(toNative.sourceType(), typeB);
+ QCOMPARE(toNative.sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)");
+ QCOMPARE(toNative.conversion().trimmed(), u"%OUT = %IN.createA();");
+ QVERIFY(conversion->targetToNativeConversions().size() > 2);
toNative = conversion->targetToNativeConversions().at(2);
- QVERIFY(toNative);
- QCOMPARE(toNative->sourceTypeName(), u"String");
- QVERIFY(toNative->isCustomType());
- QCOMPARE(toNative->sourceType(), nullptr);
- QCOMPARE(toNative->sourceTypeCheck(), u"String_Check(%IN)");
- QCOMPARE(toNative->conversion().trimmed(), u"%OUT = new A(String_AsString(%IN), String_GetSize(%IN));");
+ QCOMPARE(toNative.sourceTypeName(), u"String");
+ QVERIFY(toNative.isCustomType());
+ QCOMPARE(toNative.sourceType(), nullptr);
+ QCOMPARE(toNative.sourceTypeCheck(), u"String_Check(%IN)");
+ QCOMPARE(toNative.conversion().trimmed(),
+ u"%OUT = new A(String_AsString(%IN), String_GetSize(%IN));");
}
void TestConversionRuleTag::testConversionRuleTagAdd()
@@ -133,7 +137,7 @@ void TestConversionRuleTag::testConversionRuleTagAdd()
Date();\n\
Date(int, int, int);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<value-type name='Date'>\n\
@@ -149,12 +153,14 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
- auto *classA = AbstractMetaClass::findClass(builder->classes(), u"Date");
+ QVERIFY(builder);
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "Date");
QVERIFY(classA);
- CustomConversion* conversion = classA->typeEntry()->customConversion();
- QVERIFY(conversion);
+ QVERIFY(classA->typeEntry()->isValue());
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(classA->typeEntry());
+ QVERIFY(vte->hasCustomConversion());
+ auto conversion = vte->customConversion();
QCOMPARE(conversion->nativeToTargetConversion(), QString());
@@ -162,14 +168,13 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\
QVERIFY(conversion->hasTargetToNativeConversions());
QCOMPARE(conversion->targetToNativeConversions().size(), 1);
- CustomConversion::TargetToNativeConversion *toNative =
- conversion->targetToNativeConversions().constFirst();
- QVERIFY(toNative);
- QCOMPARE(toNative->sourceTypeName(), u"TargetDate");
- QVERIFY(toNative->isCustomType());
- QCOMPARE(toNative->sourceType(), nullptr);
- QCOMPARE(toNative->sourceTypeCheck(), u"TargetDate_Check(%IN)");
- QCOMPARE(toNative->conversion().trimmed(),
+ QVERIFY(!conversion->targetToNativeConversions().isEmpty());
+ const auto &toNative = conversion->targetToNativeConversions().constFirst();
+ QCOMPARE(toNative.sourceTypeName(), u"TargetDate");
+ QVERIFY(toNative.isCustomType());
+ QCOMPARE(toNative.sourceType(), nullptr);
+ QCOMPARE(toNative.sourceTypeCheck(), u"TargetDate_Check(%IN)");
+ QCOMPARE(toNative.conversion().trimmed(),
uR"(if (!TargetDateTimeAPI) TargetDateTime_IMPORT;
%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));)");
}
@@ -177,7 +182,7 @@ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\
void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate()
{
const char cppCode[] = "struct A {};";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<!-- single line -->\n\
@@ -211,13 +216,13 @@ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate()
"// TEMPLATE - target_to_native - END";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
- TypeDatabase* typeDb = TypeDatabase::instance();
- PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s);
+ QVERIFY(builder);
+ auto *typeDb = TypeDatabase::instance();
+ auto typeA = typeDb->findPrimitiveType(u"A"_s);
QVERIFY(typeA);
- CustomConversion* conversion = typeA->customConversion();
- QVERIFY(conversion);
+ QVERIFY(typeA->hasCustomConversion());
+ auto conversion = typeA->customConversion();
QCOMPARE(typeA, conversion->ownerType());
QCOMPARE(conversion->nativeToTargetConversion().trimmed(),
@@ -226,9 +231,9 @@ void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate()
QVERIFY(conversion->hasTargetToNativeConversions());
QCOMPARE(conversion->targetToNativeConversions().size(), 1);
- CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().constFirst();
- QVERIFY(toNative);
- QCOMPARE(toNative->conversion().trimmed(),
+ QVERIFY(!conversion->targetToNativeConversions().isEmpty());
+ const auto &toNative = conversion->targetToNativeConversions().constFirst();
+ QCOMPARE(toNative.conversion().trimmed(),
QLatin1StringView(targetToNativeExpected));
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp
index 6e6a86d17..c3a3ebef0 100644
--- a/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testctorinformation.cpp
@@ -10,47 +10,47 @@
void TestCtorInformation::testCtorIsPrivate()
{
- const char* cppCode = "class Control { public: Control() {} };\n\
+ const char cppCode[] = "class Control { public: Control() {} };\n\
class Subject { private: Subject() {} };\n\
class CtorLess { };\n";
- const char* xmlCode = "<typesystem package='Foo'>\n\
+ const char xmlCode[] = "<typesystem package='Foo'>\n\
<value-type name='Control'/>\n\
<object-type name='Subject'/>\n\
<value-type name='CtorLess'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- auto *klass = AbstractMetaClass::findClass(classes, u"Control");
+ auto klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(klass->hasNonPrivateConstructor());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(!klass->hasNonPrivateConstructor());
- klass = AbstractMetaClass::findClass(classes, u"CtorLess");
+ klass = AbstractMetaClass::findClass(classes, "CtorLess");
QVERIFY(klass);
QVERIFY(klass->hasNonPrivateConstructor());
}
void TestCtorInformation::testHasNonPrivateCtor()
{
- const char* cppCode = "template<typename T>\n\
+ const char cppCode[] = "template<typename T>\n\
struct Base { Base(double) {} };\n\
typedef Base<int> Derived;\n";
- const char* xmlCode = "<typesystem package='Foo'>\n\
+ const char xmlCode[] = "<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<primitive-type name='double'/>\n\
<object-type name='Base' generate='no'/>\n\
<object-type name='Derived'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- const AbstractMetaClass *base = AbstractMetaClass::findClass(classes, u"Base");
+ const auto base = AbstractMetaClass::findClass(classes, "Base");
QCOMPARE(base->hasNonPrivateConstructor(), true);
- const AbstractMetaClass *derived = AbstractMetaClass::findClass(classes, u"Derived");
+ const auto derived = AbstractMetaClass::findClass(classes, "Derived");
QCOMPARE(derived->hasNonPrivateConstructor(), true);
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp
index b6f06458d..16f50e69d 100644
--- a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp
@@ -14,7 +14,7 @@
using namespace Qt::StringLiterals;
-static const char* cppCode ="\
+static const char cppCode[] = "\
struct ValueA {};\n\
struct ValueB {};\n\
struct ObjectA {};\n\
@@ -29,7 +29,7 @@ static const char* cppCode ="\
void funcA();\n\
void funcB();\n";
-static const char* xmlCode = "\
+static const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<value-type name='ValueA'/>\n\
<value-type name='ValueB'/>\n\
@@ -56,22 +56,22 @@ void TestDropTypeEntries::testDropEntries()
u"Foo.NamespaceA.InnerNamespaceA"_s};
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false,
QString(), droppedEntries));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA"));
- QVERIFY(!AbstractMetaClass::findClass(classes, u"ValueB"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA"));
- QVERIFY(!AbstractMetaClass::findClass(classes, u"ObjectB"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA"));
- QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA"));
- QVERIFY(!AbstractMetaClass::findClass(classes, u"NamespaceB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ValueA"));
+ QVERIFY(!AbstractMetaClass::findClass(classes, "ValueB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA"));
+ QVERIFY(!AbstractMetaClass::findClass(classes, "ObjectB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA"));
+ QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA"));
+ QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceB"));
AbstractMetaEnumList globalEnums = builder->globalEnums();
QCOMPARE(globalEnums.size(), 1);
QCOMPARE(globalEnums.constFirst().name(), u"EnumA");
- TypeDatabase* td = TypeDatabase::instance();
+ auto *td = TypeDatabase::instance();
QVERIFY(td->findType(u"funcA"_s));
QVERIFY(!td->findType(u"funcB"_s));
}
@@ -79,30 +79,30 @@ void TestDropTypeEntries::testDropEntries()
void TestDropTypeEntries::testDontDropEntries()
{
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- QVERIFY(AbstractMetaClass::findClass(classes, u"ValueA"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"ValueB"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectA"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"ObjectB"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceA::InnerClassA"));
- QVERIFY(AbstractMetaClass::findClass(classes, u"NamespaceB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ValueA"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ValueB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "ObjectB"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceB"));
QCOMPARE(builder->globalEnums().size(), 2);
- TypeDatabase* td = TypeDatabase::instance();
+ auto *td = TypeDatabase::instance();
QVERIFY(td->findType(u"funcA"_s));
QVERIFY(td->findType(u"funcB"_s));
}
-static const char* cppCode2 ="\
+static const char cppCode2[] = "\
struct ValueA {\n\
void func();\n\
};\n";
-static const char* xmlCode2 = R"(
+static const char xmlCode2[] = R"(
<typesystem package='Foo'>
<value-type name='ValueA'>
<modify-function signature='func()' remove='all'/>
@@ -115,21 +115,21 @@ void TestDropTypeEntries::testDropEntryWithChildTags()
QStringList droppedEntries(u"Foo.ValueA"_s);
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false,
QString(), droppedEntries));
- QVERIFY(!builder.isNull());
- QVERIFY(!AbstractMetaClass::findClass(builder->classes(), u"ValueA"));
+ QVERIFY(builder);
+ QVERIFY(!AbstractMetaClass::findClass(builder->classes(), "ValueA"));
}
void TestDropTypeEntries::testDontDropEntryWithChildTags()
{
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false));
- QVERIFY(!builder.isNull());
- QVERIFY(AbstractMetaClass::findClass(builder->classes(), u"ValueA"));
+ QVERIFY(builder);
+ QVERIFY(AbstractMetaClass::findClass(builder->classes(), "ValueA"));
}
void TestDropTypeEntries::testConditionalParsing_data()
{
- const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?>
+ const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag1>text</tag1>
<?if keyword1?>
@@ -145,17 +145,17 @@ void TestDropTypeEntries::testConditionalParsing_data()
<?if !keyword99?> <!-- Exclusion only -->
<tag6>text</tag6>
<?endif?>
-</root>)");
-
- const QString root = QStringLiteral("root");
- const QString tag1 = QStringLiteral("tag1");
- const QString tag2 = QStringLiteral("tag2");
- const QString tag3 = QStringLiteral("tag3");
- const QString tag4 = QStringLiteral("tag4");
- const QString tag5 = QStringLiteral("tag5");
- const QString tag6 = QStringLiteral("tag6");
- const QString keyword1 = QStringLiteral("keyword1");
- const QString keyword2 = QStringLiteral("keyword2");
+</root>)"_L1;
+
+ constexpr auto root = "root"_L1;
+ constexpr auto tag1 = "tag1"_L1;
+ constexpr auto tag2 = "tag2"_L1;
+ constexpr auto tag3 = "tag3"_L1;
+ constexpr auto tag4 = "tag4"_L1;
+ constexpr auto tag5 = "tag5"_L1;
+ constexpr auto tag6 = "tag6"_L1;
+ constexpr auto keyword1 = "keyword1"_L1;
+ constexpr auto keyword2 = "keyword2"_L1;
QTest::addColumn<QString>("xml");
QTest::addColumn<QStringList>("keywords");
@@ -204,11 +204,11 @@ void TestDropTypeEntries::testConditionalParsing()
void TestDropTypeEntries::testEntityParsing()
{
- const QString xml = QStringLiteral(R"(<?xml version="1.0" encoding="UTF-8"?>
+ const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?>
<root>
<?entity testentity word1 word2?>
<text>bla &testentity;</text>
-</root>)");
+</root>)"_L1;
QString actual;
ConditionalStreamReader reader(xml);
diff --git a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp
index add5a42da..2152d39de 100644
--- a/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testdtorinformation.cpp
@@ -25,13 +25,13 @@ private:
</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto *klass = AbstractMetaClass::findClass(classes, u"Control");
+ auto klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(!klass->hasPrivateDestructor());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(klass->hasPrivateDestructor());
}
@@ -53,13 +53,13 @@ protected:
</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto *klass = AbstractMetaClass::findClass(classes, u"Control");
+ auto klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(!klass->hasProtectedDestructor());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(klass->hasProtectedDestructor());
}
@@ -81,46 +81,46 @@ protected:
</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto *klass = AbstractMetaClass::findClass(classes, u"Control");
+ auto klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(!klass->hasVirtualDestructor());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(klass->hasVirtualDestructor());
}
void TestDtorInformation::testDtorFromBaseIsVirtual()
{
- const char* cppCode = R"CPP(class ControlBase { public: ~ControlBase() {} };
+ const char cppCode[] = R"CPP(class ControlBase { public: ~ControlBase() {} };
class Control : public ControlBase {};
class SubjectBase { public: virtual ~SubjectBase() {} };
class Subject : public SubjectBase {};
)CPP";
- const char* xmlCode = R"XML(<typesystem package="Foo"><value-type name="ControlBase"/>
+ const char xmlCode[] = R"XML(<typesystem package="Foo"><value-type name="ControlBase"/>
<value-type name="Control"/>"
<value-type name="SubjectBase"/>"
<value-type name="Subject"/>
</typesystem>
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 4);
- auto klass = AbstractMetaClass::findClass(classes, u"ControlBase");
+ auto klass = AbstractMetaClass::findClass(classes, "ControlBase");
QVERIFY(klass);
QVERIFY(!klass->hasVirtualDestructor());
- klass = AbstractMetaClass::findClass(classes, u"Control");
+ klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(!klass->hasVirtualDestructor());
- klass = AbstractMetaClass::findClass(classes, u"SubjectBase");
+ klass = AbstractMetaClass::findClass(classes, "SubjectBase");
QVERIFY(klass);
QVERIFY(klass->hasVirtualDestructor());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(klass->hasVirtualDestructor());
}
@@ -142,13 +142,13 @@ protected:
</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto *klass = AbstractMetaClass::findClass(classes, u"Control");
+ auto klass = AbstractMetaClass::findClass(classes, "Control");
QVERIFY(klass);
QVERIFY(klass->isPolymorphic());
- klass = AbstractMetaClass::findClass(classes, u"Subject");
+ klass = AbstractMetaClass::findClass(classes, "Subject");
QVERIFY(klass);
QVERIFY(klass->isPolymorphic());
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testenum.cpp b/sources/shiboken6/ApiExtractor/tests/testenum.cpp
index 9fd413ddc..c7c2b8b3b 100644
--- a/sources/shiboken6/ApiExtractor/tests/testenum.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testenum.cpp
@@ -3,6 +3,7 @@
#include "testenum.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetaenum.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
@@ -19,7 +20,7 @@ using namespace Qt::StringLiterals;
void TestEnum::testEnumCppSignature()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
enum GlobalEnum { A, B };\n\
\n\
struct A {\n\
@@ -27,7 +28,7 @@ void TestEnum::testEnumCppSignature()
void method(ClassEnum);\n\
};\n\
void func(A::ClassEnum);\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<enum-type name='GlobalEnum'/>\n\
<value-type name='A'>\n\
@@ -37,7 +38,7 @@ void TestEnum::testEnumCppSignature()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
@@ -53,7 +54,7 @@ void TestEnum::testEnumCppSignature()
u"A::ClassEnum");
// enum as parameter of a method
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QCOMPARE(classA->enums().size(), 1);
const auto funcs = classA->queryFunctionsByName(u"method"_s);
QVERIFY(!funcs.isEmpty());
@@ -77,12 +78,12 @@ void TestEnum::testEnumCppSignature()
void TestEnum::testEnumWithApiVersion()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
enum ClassEnum { EnumA, EnumB };\n\
enum ClassEnum2 { EnumC, EnumD };\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<value-type name='A'>\n\
<enum-type name='ClassEnum' since='0.1'/>\n\
@@ -92,7 +93,7 @@ void TestEnum::testEnumWithApiVersion()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
true, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
QCOMPARE(classes[0]->enums().size(), 1);
@@ -100,13 +101,13 @@ void TestEnum::testEnumWithApiVersion()
void TestEnum::testAnonymousEnum()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
enum { Global0, Global1 };\n\
struct A {\n\
enum { A0, A1 };\n\
enum { isThis = true, isThat = false };\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<!-- Uses the first value of the enum to identify it. -->\n\
<enum-type identified-by-value='Global0'/>\n\
@@ -118,7 +119,7 @@ void TestEnum::testAnonymousEnum()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaEnumList globalEnums = builder->globalEnums();
QCOMPARE(globalEnums.size(), 1);
@@ -163,17 +164,17 @@ void TestEnum::testAnonymousEnum()
void TestEnum::testGlobalEnums()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
enum EnumA { A0, A1 };\n\
enum EnumB { B0 = 2, B1 = 0x4 };\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<enum-type name='EnumA'/>\n\
<enum-type name='EnumB'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaEnumList globalEnums = builder->globalEnums();
QCOMPARE(globalEnums.size(), 2);
@@ -207,12 +208,12 @@ void TestEnum::testGlobalEnums()
void TestEnum::testEnumValueFromNeighbourEnum()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
namespace A {\n\
enum EnumA { ValueA0, ValueA1 };\n\
enum EnumB { ValueB0 = A::ValueA1, ValueB1 = ValueA0 };\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<namespace-type name='A'>\n\
<enum-type name='EnumA'/>\n\
@@ -221,7 +222,7 @@ void TestEnum::testEnumValueFromNeighbourEnum()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
@@ -258,7 +259,7 @@ void TestEnum::testEnumValueFromNeighbourEnum()
void TestEnum::testEnumValueFromExpression()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
enum EnumA : unsigned {\n\
ValueA0 = 3u,\n\
@@ -274,7 +275,7 @@ void TestEnum::testEnumValueFromExpression()
ValueB0 = ~3,\n\
};\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<value-type name='A'>\n\
<enum-type name='EnumA'/>\n\
@@ -283,9 +284,9 @@ void TestEnum::testEnumValueFromExpression()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ AbstractMetaClassPtr classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
auto enumA = classA->findEnum(u"EnumA"_s);
@@ -346,14 +347,14 @@ void TestEnum::testEnumValueFromExpression()
void TestEnum::testPrivateEnum()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class A {\n\
private:\n\
enum PrivateEnum { Priv0 = 0x0f, Priv1 = 0xf0 };\n\
public:\n\
enum PublicEnum { Pub0 = Priv0, Pub1 = A::Priv1 };\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<value-type name='A'>\n\
<enum-type name='PublicEnum'/>\n\
@@ -361,9 +362,9 @@ void TestEnum::testPrivateEnum()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
QCOMPARE(classA->enums().size(), 2);
@@ -389,18 +390,18 @@ void TestEnum::testPrivateEnum()
void TestEnum::testTypedefEnum()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
typedef enum EnumA {\n\
A0,\n\
A1,\n\
} EnumA;\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<enum-type name='EnumA'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaEnumList globalEnums = builder->globalEnums();
QCOMPARE(globalEnums.size(), 1);
@@ -425,7 +426,7 @@ void TestEnum::testTypedefEnum()
struct EnumDefaultValuesFixture
{
- QSharedPointer<AbstractMetaBuilder> builder;
+ std::shared_ptr<AbstractMetaBuilder> builder;
AbstractMetaType globalEnum;
AbstractMetaType testEnum;
@@ -461,7 +462,7 @@ namespace Test2
)";
fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false));
- if (fixture->builder.isNull())
+ if (!fixture->builder)
return -1;
const auto globalEnums = fixture->builder->globalEnums();
@@ -471,8 +472,8 @@ namespace Test2
fixture->globalEnum = AbstractMetaType(globalEnums.constFirst().typeEntry());
fixture->globalEnum.decideUsagePattern();
- const AbstractMetaClass *testNamespace = nullptr;
- for (auto *c : fixture->builder->classes()) {
+ AbstractMetaClassCPtr testNamespace;
+ for (const auto &c : fixture->builder->classes()) {
if (c->name() == u"Test2") {
testNamespace = c;
break;
@@ -484,9 +485,9 @@ namespace Test2
const auto namespaceEnums = testNamespace->enums();
if (namespaceEnums.size() != 2)
return -4;
- QList<const EnumTypeEntry *> enumTypeEntries{
- static_cast<const EnumTypeEntry *>(namespaceEnums.at(0).typeEntry()),
- static_cast<const EnumTypeEntry *>(namespaceEnums.at(1).typeEntry())};
+ QList<EnumTypeEntryCPtr > enumTypeEntries{
+ std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(0).typeEntry()),
+ std::static_pointer_cast<const EnumTypeEntry>(namespaceEnums.at(1).typeEntry())};
if (enumTypeEntries.constFirst()->flags())
std::swap(enumTypeEntries[0], enumTypeEntries[1]);
fixture->testEnum = AbstractMetaType(enumTypeEntries.at(0));
diff --git a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp
index f540074e9..fcc409a42 100644
--- a/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testextrainclude.cpp
@@ -10,8 +10,8 @@
void TestExtraInclude::testClassExtraInclude()
{
- const char* cppCode ="struct A {};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A {};\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<value-type name='A'>\n\
<extra-includes>\n\
@@ -21,9 +21,9 @@ void TestExtraInclude::testClassExtraInclude()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QList<Include> includes = classA->typeEntry()->extraIncludes();
@@ -33,8 +33,8 @@ void TestExtraInclude::testClassExtraInclude()
void TestExtraInclude::testGlobalExtraIncludes()
{
- const char* cppCode ="struct A {};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A {};\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<extra-includes>\n\
<include file-name='header1.h' location='global'/>\n\
@@ -44,12 +44,12 @@ void TestExtraInclude::testGlobalExtraIncludes()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- QVERIFY(AbstractMetaClass::findClass(classes, u"A"));
+ QVERIFY(AbstractMetaClass::findClass(classes, "A"));
- TypeDatabase* td = TypeDatabase::instance();
- const TypeSystemTypeEntry *module = td->defaultTypeSystemType();
+ auto *td = TypeDatabase::instance();
+ TypeSystemTypeEntryCPtr module = td->defaultTypeSystemType();
QVERIFY(module);
QCOMPARE(module->name(), u"Foo");
diff --git a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp
index 66c2e08c9..18eaf5774 100644
--- a/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testfunctiontag.cpp
@@ -23,9 +23,9 @@ void TestFunctionTag::testFunctionTagForSpecificSignature()
<function signature='globalFunction(int)'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- const TypeEntry *func = TypeDatabase::instance()->findType(u"globalFunction"_s);
+ TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s);
QVERIFY(func);
QCOMPARE(builder->globalFunctions().size(), 1);
}
@@ -41,24 +41,24 @@ void TestFunctionTag::testFunctionTagForAllSignatures()
<function signature='globalFunction(float)'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- const TypeEntry *func = TypeDatabase::instance()->findType(u"globalFunction"_s);
+ TypeEntryCPtr func = TypeDatabase::instance()->findType(u"globalFunction"_s);
QVERIFY(func);
QCOMPARE(builder->globalFunctions().size(), 2);
}
void TestFunctionTag::testRenameGlobalFunction()
{
- const char* cppCode ="void global_function_with_ugly_name();\n";
- const char* xmlCode = "\
+ const char cppCode[] = "void global_function_with_ugly_name();\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<function signature='global_function_with_ugly_name()' rename='smooth'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- const TypeEntry *func = TypeDatabase::instance()->findType(u"global_function_with_ugly_name"_s);
+ TypeEntryCPtr func = TypeDatabase::instance()->findType(u"global_function_with_ugly_name"_s);
QVERIFY(func);
QCOMPARE(builder->globalFunctions().size(), 1);
diff --git a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp
index f600c3ea9..899d00ad4 100644
--- a/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testimplicitconversions.cpp
@@ -3,14 +3,16 @@
#include "testimplicitconversions.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <complextypeentry.h>
#include <QtTest/QTest>
void TestImplicitConversions::testWithPrivateCtors()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class B;\n\
class C;\n\
class A {\n\
@@ -20,19 +22,19 @@ void TestImplicitConversions::testWithPrivateCtors()
};\n\
class B {};\n\
class C {};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<value-type name='A'/>\n\
<value-type name='B'/>\n\
<value-type name='C'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classC = AbstractMetaClass::findClass(classes, "C");
const auto implicitConvs = classA->implicitConversions();
QCOMPARE(implicitConvs.size(), 1);
QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(),
@@ -41,14 +43,14 @@ void TestImplicitConversions::testWithPrivateCtors()
void TestImplicitConversions::testWithModifiedVisibility()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class B;\n\
class A {\n\
public:\n\
A(const B&);\n\
};\n\
class B {};\n";
- const char* xmlCode = R"(
+ const char xmlCode[] = R"(
<typesystem package='Foo'>
<value-type name='A'>
<modify-function signature='A(const B&amp;)' access='private'/>
@@ -57,11 +59,11 @@ void TestImplicitConversions::testWithModifiedVisibility()
</typesystem>
)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
const auto implicitConvs = classA->implicitConversions();
QCOMPARE(implicitConvs.size(), 1);
QCOMPARE(implicitConvs.constFirst()->arguments().constFirst().type().typeEntry(),
@@ -71,7 +73,7 @@ void TestImplicitConversions::testWithModifiedVisibility()
void TestImplicitConversions::testWithAddedCtor()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class B;\n\
class A {\n\
public:\n\
@@ -79,7 +81,7 @@ void TestImplicitConversions::testWithAddedCtor()
};\n\
class B {};\n\
class C {};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<custom-type name='TARGETLANGTYPE'/>\n\
<value-type name='A'>\n\
@@ -91,38 +93,38 @@ void TestImplicitConversions::testWithAddedCtor()
<value-type name='C'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
auto implicitConvs = classA->implicitConversions();
QCOMPARE(implicitConvs.size(), 2);
// Added constructors with custom types should never result in implicit converters.
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
implicitConvs = classB->implicitConversions();
QCOMPARE(implicitConvs.size(), 0);
}
void TestImplicitConversions::testWithExternalConversionOperator()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
class A {};\n\
struct B {\n\
operator A() const;\n\
};\n";
- const char* xmlCode = "\n\
+ const char xmlCode[] = "\n\
<typesystem package='Foo'>\n\
<value-type name='A'/>\n\
<value-type name='B'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
const auto implicitConvs = classA->implicitConversions();
QCOMPARE(implicitConvs.size(), 1);
const auto &externalConvOps = classA->externalConversionOperators();
@@ -133,7 +135,7 @@ void TestImplicitConversions::testWithExternalConversionOperator()
if (func->isConversionOperator())
convOp = func;
}
- QVERIFY(!convOp.isNull());
+ QVERIFY(convOp);
QCOMPARE(implicitConvs.constFirst(), convOp);
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp
index 416f9c792..23cf0f9ea 100644
--- a/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testinserttemplate.cpp
@@ -12,8 +12,8 @@
void TestInsertTemplate::testInsertTemplateOnClassInjectCode()
{
- const char* cppCode ="struct A{};\n";
- const char* xmlCode = "\
+ const char cppCode[] = "struct A{};\n";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<template name='code_template'>\n\
code template content\n\
@@ -25,10 +25,10 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->typeEntry()->codeSnips().size(), 1);
QString code = classA->typeEntry()->codeSnips().constFirst().code();
@@ -37,8 +37,8 @@ void TestInsertTemplate::testInsertTemplateOnClassInjectCode()
void TestInsertTemplate::testInsertTemplateOnModuleInjectCode()
{
- const char* cppCode ="";
- const char* xmlCode = "\
+ const char cppCode[] = "";
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<template name='code_template'>\n\
code template content\n\
@@ -48,14 +48,13 @@ void TestInsertTemplate::testInsertTemplateOnModuleInjectCode()
</inject-code>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QVERIFY(classes.isEmpty());
- const TypeSystemTypeEntry *module = TypeDatabase::instance()->defaultTypeSystemType();
+ TypeSystemTypeEntryCPtr module = TypeDatabase::instance()->defaultTypeSystemType();
QVERIFY(module);
QCOMPARE(module->name(), u"Foo");
- QVERIFY(module);
QCOMPARE(module->codeSnips().size(), 1);
QString code = module->codeSnips().constFirst().code().trimmed();
QVERIFY(code.contains(u"code template content"));
diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
index 05fd3bf6b..9cf2e0cc7 100644
--- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
@@ -4,6 +4,7 @@
#include "testmodifydocumentation.h"
#include "testutil.h"
#include <abstractmetalang.h>
+#include <abstractmetafunction.h>
#include <documentation.h>
#include <modifications.h>
#include <complextypeentry.h>
@@ -19,7 +20,7 @@ using namespace Qt::StringLiterals;
void TestModifyDocumentation::testModifyDocumentation()
{
- const char* cppCode ="struct B { void b(); }; class A {};\n";
+ const char cppCode[] = "struct B { void b(); }; class A {};\n";
const char xmlCode[] =
R"(<typesystem package="Foo">
<value-type name='B'>
@@ -32,8 +33,8 @@ R"(<typesystem package="Foo">
</typesystem>
)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
- AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ QVERIFY(builder);
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
DocModificationList docMods = classA->typeEntry()->docModifications();
QCOMPARE(docMods.size(), 2);
@@ -46,7 +47,7 @@ R"(<typesystem package="Foo">
// cannot handle Qt resources.
QTemporaryDir tempDir(QDir::tempPath() + u"/shiboken_testmodifydocXXXXXX"_s);
QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString()));
- const QString docFileName = u"a.xml"_s;
+ constexpr auto docFileName = "a.xml"_L1;
QVERIFY(QFile::copy(u":/"_s + docFileName, tempDir.filePath(docFileName)));
QtDocParser docParser;
@@ -78,6 +79,33 @@ R"(<?xml version="1.0"?>
QCOMPARE(actualDocSimplified, expectedDocSimplified);
}
+void TestModifyDocumentation::testInjectAddedFunctionDocumentation()
+{
+ const char cppCode[] ="class A {};\n";
+ const char xmlCode[] = R"XML(
+<typesystem package="Foo">
+ <value-type name='A'>
+ <add-function signature="foo(int@parameter_name@)">
+ <inject-documentation format="target" mode="append">
+ Injected documentation of added function foo.
+ </inject-documentation>
+ </add-function>
+ </value-type>
+</typesystem>
+)XML";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(builder);
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
+ QVERIFY(classA);
+ const auto f = classA->findFunction("foo");
+ QVERIFY(f);
+ QVERIFY(f->isUserAdded());
+ auto docMods = f->addedFunctionDocModifications();
+ QCOMPARE(docMods.size(), 1);
+ const QString code = docMods.constFirst().code();
+ QVERIFY(code.contains(u"Injected documentation of added function foo."));
+}
+
// We expand QTEST_MAIN macro but using QCoreApplication instead of QApplication
// because this test needs an event loop but can't use QApplication to avoid a crash
// on our ARMEL/FRAMANTLE buildbot
diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h
index c7479f23e..c1cc8f480 100644
--- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h
+++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.h
@@ -11,6 +11,7 @@ class TestModifyDocumentation : public QObject
Q_OBJECT
private slots:
void testModifyDocumentation();
+ void testInjectAddedFunctionDocumentation();
};
#endif
diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp
index 837564051..a7d40f70a 100644
--- a/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testmodifyfunction.cpp
@@ -3,9 +3,11 @@
#include "testmodifyfunction.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetabuilder_p.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <modifications.h>
#include <typesystem.h>
@@ -26,7 +28,7 @@ void TestModifyFunction::testRenameArgument()
{
QFETCH(QByteArray, pattern);
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
void method(int=0);\n\
};\n";
@@ -44,23 +46,23 @@ void TestModifyFunction::testRenameArgument()
const QByteArray xmlCode = QByteArray(xmlCode1) + pattern + QByteArray(xmlCode2);
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.constData(), false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
- const auto func = classA->findFunction(u"method");
- QVERIFY(!func.isNull());
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ const auto func = classA->findFunction("method");
+ QVERIFY(func);
QCOMPARE(func->argumentName(1), u"otherArg");
}
void TestModifyFunction::testOwnershipTransfer()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {\n\
virtual A* method();\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<object-type name='A' />\n\
<object-type name='B'>\n\
@@ -72,11 +74,11 @@ void TestModifyFunction::testOwnershipTransfer()
</object-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
- const auto func = classB->findFunction(u"method");
- QVERIFY(!func.isNull());
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ const auto func = classB->findFunction("method");
+ QVERIFY(func);
QCOMPARE(func->argumentTargetOwnership(func->ownerClass(), 0),
TypeSystem::CppOwnership);
@@ -85,7 +87,7 @@ void TestModifyFunction::testOwnershipTransfer()
void TestModifyFunction::invalidateAfterUse()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
virtual void call(int *a);\n\
};\n\
@@ -99,7 +101,7 @@ void TestModifyFunction::invalidateAfterUse()
};\n\
struct E : D {\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='int'/>\n\
<object-type name='A'>\n\
@@ -122,47 +124,47 @@ void TestModifyFunction::invalidateAfterUse()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
false, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
- auto func = classB->findFunction(u"call");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ auto func = classB->findFunction("call");
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C");
+ const auto classC = AbstractMetaClass::findClass(classes, "C");
QVERIFY(classC);
- func = classC->findFunction(u"call");
+ func = classC->findFunction("call");
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- func = classC->findFunction(u"call2");
+ func = classC->findFunction("call2");
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D");
+ AbstractMetaClassCPtr classD = AbstractMetaClass::findClass(classes, "D");
QVERIFY(classD);
- func = classD->findFunction(u"call");
+ func = classD->findFunction("call");
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- func = classD->findFunction(u"call2");
+ func = classD->findFunction("call2");
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- const AbstractMetaClass *classE = AbstractMetaClass::findClass(classes, u"E");
+ const auto classE = AbstractMetaClass::findClass(classes, "E");
QVERIFY(classE);
- func = classE->findFunction(u"call");
+ func = classE->findFunction("call");
QVERIFY(func);
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
QVERIFY(func->modifications().at(0).argument_mods().at(0).resetAfterUse());
- func = classE->findFunction(u"call2");
+ func = classE->findFunction("call2");
QVERIFY(func);
QCOMPARE(func->modifications().size(), 1);
QCOMPARE(func->modifications().at(0).argument_mods().size(), 1);
@@ -171,13 +173,13 @@ void TestModifyFunction::invalidateAfterUse()
void TestModifyFunction::testWithApiVersion()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {\n\
virtual A* method();\n\
virtual B* methodB();\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<object-type name='A' />\n\
<object-type name='B'>\n\
@@ -195,15 +197,15 @@ void TestModifyFunction::testWithApiVersion()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
false, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
- auto func = classB->findFunction(u"method");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ auto func = classB->findFunction("method");
auto returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0);
QCOMPARE(returnOwnership, TypeSystem::CppOwnership);
- func = classB->findFunction(u"methodB");
+ func = classB->findFunction("methodB");
returnOwnership = func->argumentTargetOwnership(func->ownerClass(), 0);
QVERIFY(returnOwnership != TypeSystem::CppOwnership);
}
@@ -234,43 +236,43 @@ struct A {
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
false, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
// Nothing specified, true
- const auto f1 = classA->findFunction(u"f1");
- QVERIFY(!f1.isNull());
+ const auto f1 = classA->findFunction("f1");
+ QVERIFY(f1);
QVERIFY(!f1->allowThread());
// 'auto' specified, should be false for nontrivial function
- const auto f2 = classA->findFunction(u"f2");
- QVERIFY(!f2.isNull());
+ const auto f2 = classA->findFunction("f2");
+ QVERIFY(f2);
QVERIFY(f2->allowThread());
// 'no' specified, should be false
- const auto f3 = classA->findFunction(u"f3");
- QVERIFY(!f3.isNull());
+ const auto f3 = classA->findFunction("f3");
+ QVERIFY(f3);
QVERIFY(!f3->allowThread());
// Nothing specified, should be false for simple getter
- const auto getter1 = classA->findFunction(u"getter1");
- QVERIFY(!getter1.isNull());
+ const auto getter1 = classA->findFunction("getter1");
+ QVERIFY(getter1);
QVERIFY(!getter1->allowThread());
// Forced to true simple getter
- const auto getter2 = classA->findFunction(u"getter2");
- QVERIFY(!getter2.isNull());
+ const auto getter2 = classA->findFunction("getter2");
+ QVERIFY(getter2);
QVERIFY(getter2->allowThread()); // Forced to true simple getter
}
void TestModifyFunction::testGlobalFunctionModification()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
void function(A* a = 0);\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='A'/>\n\
<function signature='function(A*)'>\n\
@@ -284,10 +286,11 @@ void TestModifyFunction::testGlobalFunctionModification()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->globalFunctions().size(), 1);
- FunctionModificationList mods = TypeDatabase::instance()->functionModifications(u"function(A*)"_s);
+ auto *td = TypeDatabase::instance();
+ FunctionModificationList mods = td->globalFunctionModifications({u"function(A*)"_s});
QCOMPARE(mods.size(), 1);
const QList<ArgumentModification> &argMods = mods.constFirst().argument_mods();
QCOMPARE(argMods.size(), 1);
@@ -431,44 +434,44 @@ void TestModifyFunction::testScopedModifications()
QFETCH(bool, expectedAllowThread);
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode.constData(), xmlCode.constData(), false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), u"A");
+ const auto classA = AbstractMetaClass::findClass(builder->classes(), "A");
QVERIFY(classA);
- auto f = classA->findFunction(QStringLiteral("unspecified"));
- QVERIFY(!f.isNull());
+ auto f = classA->findFunction("unspecified");
+ QVERIFY(f);
QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Unknown);
QCOMPARE(f->generateExceptionHandling(), expectedGenerateUnspecified);
QCOMPARE(f->allowThread(), expectedAllowThread);
- f = classA->findFunction(QStringLiteral("nonThrowing"));
- QVERIFY(!f.isNull());
+ f = classA->findFunction("nonThrowing");
+ QVERIFY(f);
QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::NoExcept);
QCOMPARE(f->generateExceptionHandling(), expectedGenerateNonThrowing);
- f = classA->findFunction(QStringLiteral("throwing"));
- QVERIFY(!f.isNull());
+ f = classA->findFunction("throwing");
+ QVERIFY(f);
QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Throws);
QCOMPARE(f->generateExceptionHandling(), expectedGenerateThrowing);
}
void TestModifyFunction::testSnakeCaseRenaming_data()
{
- QTest::addColumn<QString>("name");
- QTest::addColumn<QString>("expected");
+ QTest::addColumn<QLatin1StringView>("name");
+ QTest::addColumn<QLatin1StringView>("expected");
QTest::newRow("s1")
- << QStringLiteral("snakeCaseFunc") << QStringLiteral("snake_case_func");
+ << "snakeCaseFunc"_L1 << "snake_case_func"_L1;
QTest::newRow("s2")
- << QStringLiteral("SnakeCaseFunc") << QStringLiteral("snake_case_func");
+ << "SnakeCaseFunc"_L1 << "snake_case_func"_L1;
QTest::newRow("consecutive-uppercase")
- << QStringLiteral("snakeCAseFunc") << QStringLiteral("snakeCAseFunc");
+ << "snakeCAseFunc"_L1 << "snakeCAseFunc"_L1;
}
void TestModifyFunction::testSnakeCaseRenaming()
{
- QFETCH(QString, name);
- QFETCH(QString, expected);
+ QFETCH(QLatin1StringView, name);
+ QFETCH(QLatin1StringView, expected);
const QString actual = AbstractMetaBuilder::getSnakeCaseName(name);
QCOMPARE(actual, expected);
diff --git a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp
index af84ef864..1cf4c8e0f 100644
--- a/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testmultipleinheritance.cpp
@@ -10,7 +10,7 @@
void TestMultipleInheritance::testVirtualClass()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
virtual ~A();\n\
virtual void theBug();\n\
@@ -22,7 +22,7 @@ void TestMultipleInheritance::testVirtualClass()
};\n\
struct D : C {\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<object-type name='A' />\n\
<object-type name='B' />\n\
@@ -31,11 +31,11 @@ void TestMultipleInheritance::testVirtualClass()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 4);
- const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"D");
+ const auto classD = AbstractMetaClass::findClass(classes, "D");
bool functionFound = false;
for (const auto &f : classD->functions()) {
if (f->name() == u"theBug") {
diff --git a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp
index 00af4d48d..3773e614a 100644
--- a/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testnamespace.cpp
@@ -15,7 +15,7 @@ using namespace Qt::StringLiterals;
void NamespaceTest::testNamespaceMembers()
{
- const char* cppCode = "\
+ const char cppCode[] = "\
namespace Namespace\n\
{\n\
enum Option {\n\
@@ -24,26 +24,26 @@ void NamespaceTest::testNamespaceMembers()
};\n\
void foo(Option opt);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='Namespace'>\n\
<enum-type name='Option' />\n\
</namespace-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass *ns = AbstractMetaClass::findClass(classes, u"Namespace");
+ const auto ns = AbstractMetaClass::findClass(classes, "Namespace");
QVERIFY(ns);
auto metaEnum = ns->findEnum(u"Option"_s);
QVERIFY(metaEnum.has_value());
- const auto func = ns->findFunction(u"foo");
- QVERIFY(!func.isNull());
+ const auto func = ns->findFunction("foo");
+ QVERIFY(func);
}
void NamespaceTest::testNamespaceInnerClassMembers()
{
- const char* cppCode = "\
+ const char cppCode[] = "\
namespace OuterNamespace\n\
{\n\
namespace InnerNamespace {\n\
@@ -52,7 +52,7 @@ void NamespaceTest::testNamespaceInnerClassMembers()
};\n\
};\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='OuterNamespace'>\n\
<namespace-type name='InnerNamespace'>\n\
@@ -61,16 +61,16 @@ void NamespaceTest::testNamespaceInnerClassMembers()
</namespace-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace");
+ const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace");
QVERIFY(ons);
- const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace");
+ const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace");
QVERIFY(ins);
- const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass");
+ const auto sc = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass");
QVERIFY(sc);
- const auto meth = sc->findFunction(u"method");
- QVERIFY(!meth.isNull());
+ const auto meth = sc->findFunction("method");
+ QVERIFY(meth);
}
QTEST_APPLESS_MAIN(NamespaceTest)
diff --git a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp
index 7f827d5aa..10ca1a0f6 100644
--- a/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testnestedtypes.cpp
@@ -5,6 +5,7 @@
#include "testutil.h"
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <codesnip.h>
#include <modifications.h>
#include <complextypeentry.h>
@@ -18,7 +19,7 @@ using namespace Qt::StringLiterals;
void TestNestedTypes::testNestedTypesModifications()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
namespace OuterNamespace {\n\
namespace InnerNamespace {\n\
struct SomeClass {\n\
@@ -26,7 +27,7 @@ void TestNestedTypes::testNestedTypesModifications()
};\n\
};\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='OuterNamespace'>\n\
<namespace-type name='InnerNamespace'>\n\
@@ -42,13 +43,13 @@ void TestNestedTypes::testNestedTypesModifications()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- auto *ons = AbstractMetaClass::findClass(classes, u"OuterNamespace");
+ const auto ons = AbstractMetaClass::findClass(classes, "OuterNamespace");
QVERIFY(ons);
- auto *ins = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace");
+ const auto ins = AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace");
QVERIFY(ins);
QCOMPARE(ins->functions().size(), 1);
QCOMPARE(ins->typeEntry()->codeSnips().size(), 1);
@@ -67,8 +68,9 @@ void TestNestedTypes::testNestedTypesModifications()
snip = addedFunc->modifications().constFirst().snips().constFirst();
QCOMPARE(snip.code().trimmed(), u"custom_code2();");
- auto *sc = AbstractMetaClass::findClass(classes, u"OuterNamespace::InnerNamespace::SomeClass");
- QVERIFY(ins);
+ const auto sc =
+ AbstractMetaClass::findClass(classes, "OuterNamespace::InnerNamespace::SomeClass");
+ QVERIFY(sc);
QCOMPARE(sc->functions().size(), 2); // default constructor and removed method
const auto removedFunc = sc->functions().constLast();
QVERIFY(removedFunc->isModifiedRemoved());
@@ -77,11 +79,11 @@ void TestNestedTypes::testNestedTypesModifications()
void TestNestedTypes::testDuplicationOfNestedTypes()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
namespace Namespace {\n\
class SomeClass {};\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<namespace-type name='Namespace'>\n\
<value-type name='SomeClass'>\n\
@@ -91,22 +93,22 @@ void TestNestedTypes::testDuplicationOfNestedTypes()
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 2);
- auto *nspace = AbstractMetaClass::findClass(classes, u"Namespace");
+ const auto nspace = AbstractMetaClass::findClass(classes, "Namespace");
QVERIFY(nspace);
- auto *cls1 = AbstractMetaClass::findClass(classes, u"SomeClass");
+ const auto cls1 = AbstractMetaClass::findClass(classes, "SomeClass");
QVERIFY(cls1);
- auto *cls2 = AbstractMetaClass::findClass(classes, u"Namespace::SomeClass");
+ const auto cls2 = AbstractMetaClass::findClass(classes, "Namespace::SomeClass");
QVERIFY(cls2);
QCOMPARE(cls1, cls2);
QCOMPARE(cls1->name(), u"SomeClass");
QCOMPARE(cls1->qualifiedCppName(), u"Namespace::SomeClass");
- TypeEntry* t1 = TypeDatabase::instance()->findType(u"Namespace::SomeClass"_s);
+ auto t1 = TypeDatabase::instance()->findType(u"Namespace::SomeClass"_s);
QVERIFY(t1);
- TypeEntry* t2 = TypeDatabase::instance()->findType(u"SomeClass"_s);
+ auto t2 = TypeDatabase::instance()->findType(u"SomeClass"_s);
QVERIFY(!t2);
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp
index 7d72aa7c7..9eef7ec47 100644
--- a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp
@@ -4,17 +4,19 @@
#include "testnumericaltypedef.h"
#include <QtTest/QTest>
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <typesystem.h>
void TestNumericalTypedef::testNumericalTypedef()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
typedef double real;\n\
void funcDouble(double);\n\
void funcReal(real);\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='double'/>\n\
<primitive-type name='real'/>\n\
@@ -22,7 +24,7 @@ void TestNumericalTypedef::testNumericalTypedef()
<function signature='funcReal(real)'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->globalFunctions().size(), 2);
auto funcDouble = builder->globalFunctions().constFirst();
@@ -38,21 +40,21 @@ void TestNumericalTypedef::testNumericalTypedef()
const AbstractMetaType doubleType = funcDouble->arguments().constFirst().type();
QCOMPARE(doubleType.cppSignature(), u"double");
QVERIFY(doubleType.isPrimitive());
- QVERIFY(doubleType.typeEntry()->isCppPrimitive());
+ QVERIFY(isCppPrimitive(doubleType.typeEntry()));
const AbstractMetaType realType = funcReal->arguments().constFirst().type();
QCOMPARE(realType.cppSignature(), u"real");
QVERIFY(realType.isPrimitive());
- QVERIFY(realType.typeEntry()->isCppPrimitive());
+ QVERIFY(isCppPrimitive(realType.typeEntry()));
}
void TestNumericalTypedef::testUnsignedNumericalTypedef()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
typedef unsigned short custom_ushort;\n\
void funcUnsignedShort(unsigned short);\n\
void funcUShort(custom_ushort);\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='short'/>\n\
<primitive-type name='unsigned short'/>\n\
@@ -61,7 +63,7 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef()
<function signature='funcUShort(custom_ushort)'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->globalFunctions().size(), 2);
auto funcUnsignedShort = builder->globalFunctions().constFirst();
@@ -76,12 +78,12 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef()
const AbstractMetaType unsignedShortType = funcUnsignedShort->arguments().constFirst().type();
QCOMPARE(unsignedShortType.cppSignature(), u"unsigned short");
QVERIFY(unsignedShortType.isPrimitive());
- QVERIFY(unsignedShortType.typeEntry()->isCppPrimitive());
+ QVERIFY(isCppPrimitive(unsignedShortType.typeEntry()));
const AbstractMetaType ushortType = funcUShort->arguments().constFirst().type();
QCOMPARE(ushortType.cppSignature(), u"custom_ushort");
QVERIFY(ushortType.isPrimitive());
- QVERIFY(ushortType.typeEntry()->isCppPrimitive());
+ QVERIFY(isCppPrimitive(ushortType.typeEntry()));
}
QTEST_APPLESS_MAIN(TestNumericalTypedef)
diff --git a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp
index 30552ff0b..99cced09d 100644
--- a/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testprimitivetypetag.cpp
@@ -14,23 +14,23 @@ using namespace Qt::StringLiterals;
void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<primitive-type name='A' default-constructor='A()'/>\n\
<object-type name='B'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
- PrimitiveTypeEntry* typeEntry = TypeDatabase::instance()->findPrimitiveType(u"A"_s);
+ auto typeEntry = TypeDatabase::instance()->findPrimitiveType(u"A"_s);
QVERIFY(typeEntry);
QVERIFY(typeEntry->hasDefaultConstructor());
QCOMPARE(typeEntry->defaultConstructor(), u"A()");
diff --git a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp
index 3ceac5fca..f2e261624 100644
--- a/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testrefcounttag.cpp
@@ -15,12 +15,12 @@ using namespace Qt::StringLiterals;
void TestRefCountTag::testReferenceCountTag()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {\n\
void keepObject(B* b);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<object-type name='A'/>\n\
<object-type name='B'>\n\
@@ -32,11 +32,11 @@ void TestRefCountTag::testReferenceCountTag()
</object-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
- const auto func = classB->findFunction(u"keepObject");
- QVERIFY(!func.isNull());
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ const auto func = classB->findFunction("keepObject");
+ QVERIFY(func);
const auto refCount =
func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst();
QCOMPARE(refCount.action, ReferenceCount::Add);
@@ -44,12 +44,12 @@ void TestRefCountTag::testReferenceCountTag()
void TestRefCountTag::testWithApiVersion()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {\n\
void keepObject(B*, B*);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<object-type name='A'/>\n\
<object-type name='B'>\n\
@@ -66,11 +66,11 @@ void TestRefCountTag::testWithApiVersion()
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode,
false, u"0.1"_s));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
- const auto func = classB->findFunction(u"keepObject");
- QVERIFY(!func.isNull());
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
+ const auto func = classB->findFunction("keepObject");
+ QVERIFY(func);
const auto refCount =
func->modifications().constFirst().argument_mods().constFirst().referenceCounts().constFirst();
QCOMPARE(refCount.action, ReferenceCount::Add);
diff --git a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp
index e82c398c4..ae85c5a86 100644
--- a/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testreferencetopointer.cpp
@@ -4,29 +4,31 @@
#include "testreferencetopointer.h"
#include <QtTest/QTest>
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <typesystem.h>
void TestReferenceToPointer::testReferenceToPointerArgument()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {\n\
void dummy(A*&);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<object-type name='A'/>\n\
<object-type name='B'/>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
- const auto func = classB->findFunction(u"dummy");
- QVERIFY(!func.isNull());
+ const auto func = classB->findFunction("dummy");
+ QVERIFY(func);
QCOMPARE(func->arguments().constFirst().type().minimalSignature(), u"A*&");
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp
index 3ec348c2a..2cc82071b 100644
--- a/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.cpp
@@ -4,18 +4,23 @@
#include "testremovefield.h"
#include <QtTest/QTest>
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafield.h>
+#include <abstractmetafunction.h>
+#include <abstractmetatype.h>
#include <abstractmetalang.h>
#include <typesystem.h>
+using namespace Qt::StringLiterals;
+
void TestRemoveField::testRemoveField()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {\n\
int fieldA;\n\
int fieldB;\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<primitive-type name='int'/>\n\
<value-type name='A'>\n\
@@ -23,15 +28,49 @@ void TestRemoveField::testRemoveField()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->fields().size(), 1);
const AbstractMetaField &fieldA = classA->fields().constFirst();
QCOMPARE(fieldA.name(), u"fieldA");
}
+// Verify that 'static constexpr' fields are seen as static/const and
+// appear fully qualified for function parameter default values.
+void TestRemoveField::testConstExprField()
+{
+ const char cppCode[] = R"(
+struct A {
+ static constexpr int constExprField = 44;
+
+ void f(int iParam=constExprField);
+};
+)";
+
+ const char xmlCode[] = R"(
+<typesystem package="Foo">
+ <value-type name='A'/>
+</typesystem>
+)";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(builder);
+ AbstractMetaClassList classes = builder->classes();
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
+ QVERIFY(classA);
+ const auto &fields = classA->fields();
+ QCOMPARE(fields.size(), 1);
+ QVERIFY(fields.constFirst().isStatic());
+ QVERIFY(fields.constFirst().type().isConstant());
+ const auto function = classA->findFunction("f"_L1);
+ QVERIFY(function);
+ const auto &arguments = function->arguments();
+ QCOMPARE(arguments.size(), 1);
+ QCOMPARE(arguments.constFirst().defaultValueExpression(), "A::constExprField"_L1);
+}
+
QTEST_APPLESS_MAIN(TestRemoveField)
diff --git a/sources/shiboken6/ApiExtractor/tests/testremovefield.h b/sources/shiboken6/ApiExtractor/tests/testremovefield.h
index febe672ce..05912d99e 100644
--- a/sources/shiboken6/ApiExtractor/tests/testremovefield.h
+++ b/sources/shiboken6/ApiExtractor/tests/testremovefield.h
@@ -11,6 +11,7 @@ class TestRemoveField : public QObject
Q_OBJECT
private slots:
void testRemoveField();
+ void testConstExprField();
};
#endif
diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp
index e7c183586..87e318e95 100644
--- a/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testremoveimplconv.cpp
@@ -4,22 +4,24 @@
#include "testremoveimplconv.h"
#include "testutil.h"
#include <QtTest/QTest>
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <complextypeentry.h>
// When a constructor able to trigger implicity conversions is removed
// it should not appear in the implicity conversion list.
void TestRemoveImplConv::testRemoveImplConv()
{
- const char* cppCode ="\
+ const char cppCode[] = "\
struct A {};\n\
struct B {};\n\
struct C {\n\
C(const A&);\n\
C(const B&);\n\
};\n";
- const char* xmlCode = "\
+ const char xmlCode[] = "\
<typesystem package=\"Foo\">\n\
<value-type name='A'/>\n\
<value-type name='B'/>\n\
@@ -28,14 +30,14 @@ void TestRemoveImplConv::testRemoveImplConv()
</value-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
- const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, u"C");
+ const auto classC = AbstractMetaClass::findClass(classes, "C");
QVERIFY(classC);
const auto implConv = classC->implicitConversions();
QCOMPARE(implConv.size(), 1);
diff --git a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp
index 3f687186e..17a069b5e 100644
--- a/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testremoveoperatormethod.cpp
@@ -15,29 +15,30 @@ using namespace Qt::StringLiterals;
void TestRemoveOperatorMethod::testRemoveOperatorMethod()
{
- const char* cppCode ="\
- #include <stdint.h>\n\
- \n\
- struct Char {};\n\
- struct ByteArray {};\n\
- struct String {};\n\
- \n\
- struct A {\n\
- A& operator>>(char&);\n\
- A& operator>>(char*);\n\
- A& operator>>(short&);\n\
- A& operator>>(unsigned short&);\n\
- A& operator>>(int&);\n\
- A& operator>>(unsigned int&);\n\
- A& operator>>(int64_t&);\n\
- A& operator>>(uint64_t&);\n\
- A& operator>>(float&);\n\
- A& operator>>(double&);\n\
- A& operator>>(Char&);\n\
- A& operator>>(ByteArray&);\n\
- A& operator>>(String&);\n\
- };\n";
- const char* xmlCode = "\
+ const char cppCode[] = R"(#include <cstdint>
+
+struct Char {};
+struct ByteArray {};
+struct String {};
+
+struct A {
+ A& operator>>(char&);
+ A& operator>>(char*);
+ A& operator>>(short&);
+ A& operator>>(unsigned short&);
+ A& operator>>(int&);
+ A& operator>>(unsigned int&);
+ A& operator>>(int64_t&);
+ A& operator>>(uint64_t&);
+ A& operator>>(float&);
+ A& operator>>(double&);
+ A& operator>>(Char&);
+ A& operator>>(ByteArray&);
+ A& operator>>(String&);
+};
+)";
+
+ const char xmlCode[] = "\
<typesystem package='Foo'>\n\
<primitive-type name='char'/>\n\
<primitive-type name='short'/>\n\
@@ -67,9 +68,9 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod()
</object-type>\n\
</typesystem>\n";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->functions().size(), 14);
QStringList removedSignatures;
@@ -85,7 +86,7 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod()
removedSignatures.append(u"operator>>(double&)"_s);
removedSignatures.append(u"operator>>(Char&)"_s);
removedSignatures.append(u"operator>>(String&)"_s);
- int notRemoved = classA->functions().size();
+ auto notRemoved = classA->functions().size();
for (const auto &f : classA->functions()) {
QCOMPARE(f->isModifiedRemoved(), bool(removedSignatures.contains(f->minimalSignature())));
notRemoved -= int(f->isModifiedRemoved());
diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp
index 8b8f02a8f..67ebcc606 100644
--- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp
@@ -3,10 +3,15 @@
#include "testresolvetype.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
+#include <abstractmetaenum.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
#include <abstractmetatype.h>
#include <complextypeentry.h>
+#include <enumtypeentry.h>
+#include <primitivetypeentry.h>
+#include <typedatabase.h>
#include <qtcompat.h>
@@ -22,7 +27,7 @@ void TestResolveType::initTestCase()
void TestResolveType::testResolveReturnTypeFromParentScope()
{
- const char* cppCode = "\n\
+ const char cppCode[] = "\n\
namespace A {\n\
struct B {\n\
struct C {};\n\
@@ -32,7 +37,7 @@ void TestResolveType::testResolveReturnTypeFromParentScope()
C* method();\n\
};\n\
};";
- const char* xmlCode = R"XML(
+ const char xmlCode[] = R"XML(
<typesystem package='Foo'>
<namespace-type name='A'>
<value-type name='B'>
@@ -42,12 +47,12 @@ void TestResolveType::testResolveReturnTypeFromParentScope()
</namespace-type>
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, u"A::D");
+ const auto classD = AbstractMetaClass::findClass(classes, "A::D");
QVERIFY(classD);
- const auto meth = classD->findFunction(u"method");
- QVERIFY(!meth.isNull());
+ const auto meth = classD->findFunction("method");
+ QVERIFY(meth);
QVERIFY(meth);
}
@@ -57,13 +62,14 @@ void TestResolveType::testResolveReturnTypeFromParentScope()
struct DefaultValuesFixture
{
- QSharedPointer<AbstractMetaBuilder> builder;
+ std::shared_ptr<AbstractMetaBuilder> builder;
AbstractMetaType intType;
AbstractMetaType stringType;
AbstractMetaType classType;
AbstractMetaType listType;
- const AbstractMetaClass *klass{};
+ AbstractMetaType enumType;
+ AbstractMetaClassCPtr klass{};
};
Q_DECLARE_METATYPE(DefaultValuesFixture)
@@ -88,6 +94,7 @@ public:
static const int INT_FIELD_1 = 42;
static const char *CHAR_FIELD_1;
+ static const Enum DefaultValue = enumValue1;
};
} // Namespace
)";
@@ -103,7 +110,7 @@ public:
)";
fixture->builder.reset(TestUtil::parse(cppCode, xmlCode, false));
- if (fixture->builder.isNull())
+ if (!fixture->builder)
return -1;
for (const auto &klass : fixture->builder->classes()) {
@@ -118,7 +125,7 @@ public:
fixture->classType = AbstractMetaType(fixture->klass->typeEntry());
fixture->classType.decideUsagePattern();
- for (const auto &f : fixture->klass->findFunctions(u"Test"_s)) {
+ for (const auto &f : fixture->klass->findFunctions("Test")) {
if (f->functionType() == AbstractMetaFunction::ConstructorFunction
&& f->arguments().size() == 1) {
const auto type = f->arguments().constFirst().type();
@@ -131,11 +138,14 @@ public:
if (fixture->intType.isVoid() || fixture->stringType.isVoid())
return -3;
- auto listFunc = fixture->klass->findFunction(u"listFunc"_s);
- if (listFunc.isNull() || listFunc->arguments().size() != 1)
+ auto listFunc = fixture->klass->findFunction("listFunc");
+ if (!listFunc || listFunc->arguments().size() != 1)
return -3;
fixture->listType = listFunc->arguments().constFirst().type();
+ fixture->enumType = AbstractMetaType(fixture->klass->enums().constFirst().typeEntry());
+ fixture->enumType.decideUsagePattern();
+
return 0;
}
@@ -210,6 +220,11 @@ void TestResolveType::testFixDefaultArguments_data()
QTest::newRow("self from enum")
<< fixture << setupOk << fixture.classType
<< "Test(enumValue1)" << expected;
+
+ // Don't qualify fields to "Test::Enum::DefaultValue"
+ QTest::newRow("enum from static field")
+ << fixture << setupOk << fixture.enumType
+ << "DefaultValue" << u"Namespace::Test::DefaultValue"_s;
}
void TestResolveType::testFixDefaultArguments()
@@ -224,5 +239,43 @@ void TestResolveType::testFixDefaultArguments()
QCOMPARE(actual, expected);
}
-QTEST_APPLESS_MAIN(TestResolveType)
+// Verify that the typedefs of the C++ 11 integer types (int32_t, ...)
+// are seen by the C++ parser, otherwise they are handled as unknown
+// primitive types, causing invalid code to be generated.
+// (see BuilderPrivate::visitHeader(),
+// sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp).
+void TestResolveType::testCppTypes()
+{
+ static const char cppCode[] =R"(
+#include <cstdint>
+class Test
+{
+public:
+ explicit Test(int32_t v);
+};
+)";
+ static const char xmlCode[] = R"(
+<typesystem package="Foo">
+ <value-type name='Test'/>
+ <primitive-type name='int32_t'/>
+</typesystem>
+)";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(builder);
+ AbstractMetaClassList classes = builder->classes();
+ const auto testClass = AbstractMetaClass::findClass(classes, "Test");
+ QVERIFY(testClass);
+
+ auto *tdb = TypeDatabase::instance();
+ auto int32TEntry = tdb->findType(u"int32_t"_s);
+ QVERIFY2(int32TEntry, "int32_t not found");
+ QVERIFY(int32TEntry->isPrimitive());
+ auto int32T = std::static_pointer_cast<const PrimitiveTypeEntry>(int32TEntry);
+ auto basicType = basicReferencedTypeEntry(int32T);
+ QVERIFY2(basicType != int32T,
+ "Typedef for int32_t not found. Check the system include paths.");
+}
+
+QTEST_APPLESS_MAIN(TestResolveType)
diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.h b/sources/shiboken6/ApiExtractor/tests/testresolvetype.h
index 2c059416d..a07855eab 100644
--- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.h
+++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.h
@@ -15,6 +15,7 @@ class TestResolveType : public QObject
void testResolveReturnTypeFromParentScope();
void testFixDefaultArguments_data();
void testFixDefaultArguments();
+ void testCppTypes();
};
#endif
diff --git a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp
index 90c613f96..f4eecff2c 100644
--- a/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testreverseoperators.cpp
@@ -4,6 +4,7 @@
#include "testreverseoperators.h"
#include <QtTest/QTest>
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
#include <typesystem.h>
@@ -24,9 +25,9 @@ void TestReverseOperators::testReverseSum()
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->functions().size(), 4);
@@ -41,10 +42,10 @@ void TestReverseOperators::testReverseSum()
}
}
- QVERIFY(!normalOp.isNull());
+ QVERIFY(normalOp);
QVERIFY(!normalOp->isReverseOperator());
QCOMPARE(normalOp->arguments().size(), 1);
- QVERIFY(!reverseOp.isNull());
+ QVERIFY(reverseOp);
QVERIFY(reverseOp->isReverseOperator());
QCOMPARE(reverseOp->arguments().size(), 1);
}
@@ -66,13 +67,13 @@ void TestReverseOperators::testReverseSumWithAmbiguity()
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QCOMPARE(classA->functions().size(), 4);
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
QCOMPARE(classB->functions().size(), 4);
@@ -86,11 +87,11 @@ void TestReverseOperators::testReverseSumWithAmbiguity()
normalOp = func;
}
}
- QVERIFY(!normalOp.isNull());
+ QVERIFY(normalOp);
QVERIFY(!normalOp->isReverseOperator());
QCOMPARE(normalOp->arguments().size(), 1);
QCOMPARE(normalOp->minimalSignature(), u"operator+(B,A)");
- QVERIFY(!reverseOp.isNull());
+ QVERIFY(reverseOp);
QVERIFY(reverseOp->isReverseOperator());
QCOMPARE(reverseOp->arguments().size(), 1);
QCOMPARE(reverseOp->minimalSignature(), u"operator+(A,B)");
@@ -110,10 +111,10 @@ void TestReverseOperators::testSpaceshipOperator()
</typesystem>)";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false,
{}, {}, LanguageLevel::Cpp20));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- const AbstractMetaClass *testClass = AbstractMetaClass::findClass(classes, u"Test");
+ const auto testClass = AbstractMetaClass::findClass(classes, "Test");
QVERIFY(testClass);
const auto &functions = testClass->functions();
// 6 operators should be synthesized
diff --git a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp
index ddd134306..ea37c6255 100644
--- a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp
@@ -3,9 +3,11 @@
#include "testtemplates.h"
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafield.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include <abstractmetatype.h>
#include <complextypeentry.h>
#include <containertypeentry.h>
@@ -53,16 +55,16 @@ namespace Internet {
</typesystem>)XML").arg(file.fileName());
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"Bookmarks");
+ const auto classB = AbstractMetaClass::findClass(classes, "Bookmarks");
QVERIFY(classB);
- const auto func = classB->findFunction(u"list");
- QVERIFY(!func.isNull());
+ const auto func = classB->findFunction("list");
+ QVERIFY(func);
AbstractMetaType funcType = func->type();
QVERIFY(!funcType.isVoid());
- QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url >");
+ QCOMPARE(funcType.cppSignature(), u"QList<Internet::Url>");
}
void TestTemplates::testTemplateOnContainers()
@@ -91,15 +93,15 @@ namespace Namespace {
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
QVERIFY(!classB->baseClass());
QVERIFY(classB->baseClassName().isEmpty());
- const auto func = classB->findFunction(u"foo");
- QVERIFY(!func.isNull());
+ const auto func = classB->findFunction("foo");
+ QVERIFY(func);
AbstractMetaType argType = func->arguments().constFirst().type();
QCOMPARE(argType.instantiations().size(), 1);
QCOMPARE(argType.typeEntry()->qualifiedCppName(), u"QList");
@@ -128,14 +130,14 @@ void func(List<int> arg) {}
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const auto globalFuncs = builder->globalFunctions();
QCOMPARE(globalFuncs.size(), 1);
const auto func = globalFuncs.constFirst();
QCOMPARE(func->minimalSignature(), u"func(List<int>)");
QCOMPARE(func->arguments().constFirst().type().cppSignature(),
- u"List<int >");
+ u"List<int>");
}
void TestTemplates::testTemplatePointerAsArgument()
@@ -153,14 +155,14 @@ void func(List<int>* arg) {}
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaFunctionCList globalFuncs = builder->globalFunctions();
QCOMPARE(globalFuncs.size(), 1);
const auto func = globalFuncs.constFirst();
QCOMPARE(func->minimalSignature(), u"func(List<int>*)");
QCOMPARE(func->arguments().constFirst().type().cppSignature(),
- u"List<int > *");
+ u"List<int> *");
}
void TestTemplates::testTemplateReferenceAsArgument()
@@ -178,14 +180,14 @@ void func(List<int>& arg) {}
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const auto globalFuncs = builder->globalFunctions();
QCOMPARE(globalFuncs.size(), 1);
const auto func = globalFuncs.constFirst();
QCOMPARE(func->minimalSignature(), u"func(List<int>&)");
QCOMPARE(func->arguments().constFirst().type().cppSignature(),
- u"List<int > &");
+ u"List<int> &");
}
void TestTemplates::testTemplateParameterFixup()
@@ -207,21 +209,20 @@ struct List {
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
const AbstractMetaClassList templates = builder->templates();
QCOMPARE(templates.size(), 1);
- const AbstractMetaClass *list = templates.constFirst();
- // Verify that the parameter of "void append(List l)" gets fixed to "List<T >"
- const auto append = list->findFunction(QStringLiteral("append"));
- QVERIFY(!append.isNull());
+ AbstractMetaClassCPtr list = templates.constFirst();
+ // Verify that the parameter of "void append(List l)" gets fixed to "List<T>"
+ const auto append = list->findFunction("append");
+ QVERIFY(append);
QCOMPARE(append->arguments().size(), 1);
- QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T >");
+ QCOMPARE(append->arguments().at(0).type().cppSignature(), u"List<T>");
// Verify that the parameter of "void erase(Iterator)" is not modified
- const auto erase = list->findFunction(QStringLiteral("erase"));
- QVERIFY(!erase.isNull());
+ const auto erase = list->findFunction("erase");
+ QVERIFY(erase);
QCOMPARE(erase->arguments().size(), 1);
- QEXPECT_FAIL("", "Clang: Some other code changes the parameter type", Abort);
QCOMPARE(erase->arguments().at(0).type().cppSignature(), u"List::Iterator");
}
@@ -248,16 +249,16 @@ struct FooBars : public ListContainer<FooBar> {};
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
AbstractMetaClassList templates = builder->templates();
QCOMPARE(classes.size(), 2);
QCOMPARE(templates.size(), 1);
- const AbstractMetaClass* foobars = AbstractMetaClass::findClass(classes, u"FooBars");
+ const auto foobars = AbstractMetaClass::findClass(classes, "FooBars");
QCOMPARE(foobars->functions().size(), 4);
- const AbstractMetaClass *lc = templates.constFirst();
+ AbstractMetaClassCPtr lc = templates.constFirst();
QCOMPARE(lc->functions().size(), 2);
}
@@ -285,10 +286,10 @@ template<SomeEnum type> struct Future {};
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
QVERIFY(!classB->baseClass());
QVERIFY(classB->baseClassName().isEmpty());
@@ -324,10 +325,10 @@ template<SomeEnum type> struct Future {};
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, u"Namespace::B");
+ const auto classB = AbstractMetaClass::findClass(classes, "Namespace::B");
QVERIFY(classB);
QVERIFY(!classB->baseClass());
QVERIFY(classB->baseClassName().isEmpty());
@@ -360,21 +361,21 @@ typedef BaseTemplateClass<TypeOne> TypeOneClass;
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 3);
- const AbstractMetaClass* base = AbstractMetaClass::findClass(classes, u"BaseTemplateClass");
+ const auto base = AbstractMetaClass::findClass(classes, "BaseTemplateClass");
QVERIFY(base);
- const AbstractMetaClass* one = AbstractMetaClass::findClass(classes, u"TypeOneClass");
+ const auto one = AbstractMetaClass::findClass(classes, "TypeOneClass");
QVERIFY(one);
QCOMPARE(one->templateBaseClass(), base);
QCOMPARE(one->functions().size(), base->functions().size());
QVERIFY(one->isTypeDef());
- const ComplexTypeEntry* oneType = one->typeEntry();
- const ComplexTypeEntry* baseType = base->typeEntry();
+ auto oneType = one->typeEntry();
+ auto baseType = base->typeEntry();
QCOMPARE(oneType->baseContainerType(), baseType);
- QCOMPARE(one->baseClassNames(), QStringList(u"BaseTemplateClass<TypeOne>"_s));
+ QCOMPARE(one->baseClassNames(), QStringList(u"NSpace::BaseTemplateClass<NSpace::TypeOne>"_s));
QVERIFY(one->hasTemplateBaseClassInstantiations());
AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations();
@@ -409,27 +410,27 @@ typedef Vector<int> IntVector;
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
QCOMPARE(classes.size(), 1);
- AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, u"IntVector");
+ const auto vector = AbstractMetaClass::findClass(classes, "IntVector");
QVERIFY(vector);
auto baseContainer = vector->typeEntry()->baseContainerType();
QVERIFY(baseContainer);
- QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(),
+ QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer.get())->containerKind(),
ContainerTypeEntry::ListContainer);
QCOMPARE(vector->functions().size(), 4);
- const auto method = vector->findFunction(u"method");
- QVERIFY(!method.isNull());
- QCOMPARE(method->signature(), u"method(const Vector<int > & vector)");
+ const auto method = vector->findFunction("method");
+ QVERIFY(method);
+ QCOMPARE(method->signature(), u"method(const Vector<int> & vector)");
- const auto otherMethod = vector->findFunction(u"otherMethod");
- QVERIFY(!otherMethod.isNull());
+ const auto otherMethod = vector->findFunction("otherMethod");
+ QVERIFY(otherMethod);
QCOMPARE(otherMethod->signature(), u"otherMethod()");
QVERIFY(!otherMethod->type().isVoid());
- QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int >");
+ QCOMPARE(otherMethod->type().cppSignature(), u"Vector<int>");
}
void TestTemplates::testNonTypeTemplates()
@@ -453,7 +454,7 @@ Array<int, 2> foo();
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
auto functions = builder->globalFunctions();
QCOMPARE(functions.size(), 1);
auto foo = functions.constFirst();
@@ -536,32 +537,30 @@ void TestTemplates::testTemplateTypeDefs()
const QByteArray cppBa = cpp.toLocal8Bit();
const QByteArray xmlBa = xml.toLocal8Bit();
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppBa.constData(), xmlBa.constData(), true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *optional = AbstractMetaClass::findClass(classes, u"Optional");
+ const auto optional = AbstractMetaClass::findClass(classes, "Optional");
QVERIFY(optional);
// Find the typedef'ed class
- const AbstractMetaClass *optionalInt =
- AbstractMetaClass::findClass(classes, u"IntOptional");
+ const auto optionalInt = AbstractMetaClass::findClass(classes, "IntOptional");
QVERIFY(optionalInt);
QCOMPARE(optionalInt->templateBaseClass(), optional);
// Find the class typedef'ed in the typesystem XML
- const AbstractMetaClass *xmlOptionalInt =
- AbstractMetaClass::findClass(classes, u"XmlIntOptional");
+ const auto xmlOptionalInt = AbstractMetaClass::findClass(classes, "XmlIntOptional");
QVERIFY(xmlOptionalInt);
QCOMPARE(xmlOptionalInt->templateBaseClass(), optional);
// Check whether the value() method now has an 'int' return
- const auto valueMethod = optionalInt->findFunction(u"value");
- QVERIFY(!valueMethod.isNull());
+ const auto valueMethod = optionalInt->findFunction("value");
+ QVERIFY(valueMethod);
QCOMPARE(valueMethod->type().cppSignature(), u"int");
// ditto for typesystem XML
- const auto xmlValueMethod = xmlOptionalInt->findFunction(u"value");
- QVERIFY(!xmlValueMethod.isNull());
+ const auto xmlValueMethod = xmlOptionalInt->findFunction("value");
+ QVERIFY(xmlValueMethod);
QCOMPARE(xmlValueMethod->type().cppSignature(), u"int");
// Check whether the m_value field is of type 'int'
@@ -607,10 +606,10 @@ public:
</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- auto testClass = AbstractMetaClass::findClass(classes, u"Test");
+ const auto testClass = AbstractMetaClass::findClass(classes, "Test");
QVERIFY(testClass);
auto fields = testClass->fields();
@@ -619,9 +618,10 @@ public:
QCOMPARE(fieldType.name(), u"Container1");
QCOMPARE(fieldType.instantiations().size(), 1);
- auto derived = AbstractMetaClass::findClass(classes, u"Derived");
+ const auto derived = AbstractMetaClass::findClass(classes, "Derived");
QVERIFY(derived);
auto base = derived->templateBaseClass();
+ QVERIFY(base);
QCOMPARE(base->name(), u"Container1");
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp
index 299993bbf..72dae8cc5 100644
--- a/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testtyperevision.cpp
@@ -18,10 +18,10 @@ using namespace Qt::StringLiterals;
void TestTypeRevision::testRevisionAttr()
{
- const char* cppCode = "class Rev_0 {};"
+ const char cppCode[] = "class Rev_0 {};"
"class Rev_1 {};"
"class Rev_2 { public: enum Rev_3 { X }; enum Rev_5 { Y }; };";
- const char* xmlCode = "<typesystem package=\"Foo\">"
+ const char xmlCode[] = "<typesystem package=\"Foo\">"
"<value-type name=\"Rev_0\"/>"
"<value-type name=\"Rev_1\" revision=\"1\"/>"
"<object-type name=\"Rev_2\" revision=\"2\">"
@@ -30,25 +30,25 @@ void TestTypeRevision::testRevisionAttr()
"</object-type>"
"</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, u"Rev_0");
+ const auto rev0 = AbstractMetaClass::findClass(classes, "Rev_0");
QCOMPARE(rev0->typeEntry()->revision(), 0);
- const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, u"Rev_1");
+ const auto rev1 = AbstractMetaClass::findClass(classes, "Rev_1");
QCOMPARE(rev1->typeEntry()->revision(), 1);
- AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, u"Rev_2");
+ const auto rev2 = AbstractMetaClass::findClass(classes, "Rev_2");
QCOMPARE(rev2->typeEntry()->revision(), 2);
auto rev3 = rev2->findEnum(u"Rev_3"_s);
QVERIFY(rev3.has_value());
QCOMPARE(rev3->typeEntry()->revision(), 3);
- FlagsTypeEntry* rev4 = rev3->typeEntry()->flags();
+ auto rev4 = rev3->typeEntry()->flags();
QCOMPARE(rev4->revision(), 4);
auto rev5 = rev2->findEnum(u"Rev_5"_s);
QVERIFY(rev5.has_value());
- const EnumTypeEntry *revEnumTypeEntry = rev5->typeEntry();
+ EnumTypeEntryCPtr revEnumTypeEntry = rev5->typeEntry();
QCOMPARE(revEnumTypeEntry->revision(), 5);
QCOMPARE(revEnumTypeEntry->flags()->revision(), 5);
}
@@ -82,7 +82,7 @@ class Bar20 {};
)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, version));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
QCOMPARE(builder->classes().size(), expectedClassCount);
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testutil.h b/sources/shiboken6/ApiExtractor/tests/testutil.h
index 7fbc7e906..dc4e3b2da 100644
--- a/sources/shiboken6/ApiExtractor/tests/testutil.h
+++ b/sources/shiboken6/ApiExtractor/tests/testutil.h
@@ -24,22 +24,22 @@ namespace TestUtil
{
ReportHandler::setSilent(silent);
ReportHandler::startTimer();
- TypeDatabase* td = TypeDatabase::instance(true);
+ auto *td = TypeDatabase::instance(true);
if (apiVersion.isEmpty())
TypeDatabase::clearApiVersions();
- else if (!TypeDatabase::setApiVersion(QStringLiteral("*"), apiVersion))
+ else if (!TypeDatabase::setApiVersion(QLatin1StringView("*"), apiVersion))
return nullptr;
td->setDropTypeEntries(dropTypeEntries);
QBuffer buffer;
// parse typesystem
buffer.setData(xmlCode);
if (!buffer.open(QIODevice::ReadOnly))
- return Q_NULLPTR;
+ return nullptr;
if (!td->parseFile(&buffer))
return nullptr;
buffer.close();
// parse C++ code
- QTemporaryFile tempSource(QDir::tempPath() + QStringLiteral("/st_XXXXXX_main.cpp"));
+ QTemporaryFile tempSource(QDir::tempPath() + QLatin1StringView("/st_XXXXXX_main.cpp"));
if (!tempSource.open()) {
qWarning().noquote().nospace() << "Creation of temporary file failed: "
<< tempSource.errorString();
diff --git a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp
index 73f2d44ca..98e30eac2 100644
--- a/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testvaluetypedefaultctortag.cpp
@@ -9,29 +9,29 @@
void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument()
{
- const char* cppCode ="\n\
+ const char cppCode[] = "\n\
struct A {\n\
A(int,int);\n\
};\n\
struct B {};\n\
";
- const char* xmlCode = "\n\
+ const char xmlCode[] = "\n\
<typesystem package='Foo'>\n\
<primitive-type name='int' />\n\
<value-type name='A' default-constructor='A(0, 0)' />\n\
<value-type name='B' />\n\
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
QVERIFY(classA->typeEntry()->hasDefaultConstructor());
QCOMPARE(classA->typeEntry()->defaultConstructor(), u"A(0, 0)");
- const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, u"B");
+ const auto classB = AbstractMetaClass::findClass(classes, "B");
QVERIFY(classB);
QVERIFY(!classB->typeEntry()->hasDefaultConstructor());
}
diff --git a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp
index 56d70336a..a600181a5 100644
--- a/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testvoidarg.cpp
@@ -4,6 +4,7 @@
#include "testvoidarg.h"
#include <QtTest/QTest>
#include "testutil.h"
+#include <abstractmetaargument.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
#include <typesystem.h>
@@ -16,12 +17,12 @@ void TestVoidArg::testVoidParsedFunction()
<value-type name='A'/>\n\
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"a");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction("a");
+ QVERIFY(addedFunc);
QCOMPARE(addedFunc->arguments().size(), 0);
}
@@ -35,12 +36,12 @@ void TestVoidArg::testVoidAddedFunction()
</value-type>\n\
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"a");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction("a");
+ QVERIFY(addedFunc);
QCOMPARE(addedFunc->arguments().size(), 0);
}
@@ -53,12 +54,12 @@ void TestVoidArg::testVoidPointerParsedFunction()
<value-type name='A' />\n\
</typesystem>";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
- QVERIFY(!builder.isNull());
+ QVERIFY(builder);
AbstractMetaClassList classes = builder->classes();
- const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A");
+ const auto classA = AbstractMetaClass::findClass(classes, "A");
QVERIFY(classA);
- const auto addedFunc = classA->findFunction(u"a");
- QVERIFY(!addedFunc.isNull());
+ const auto addedFunc = classA->findFunction("a");
+ QVERIFY(addedFunc);
QCOMPARE(addedFunc->arguments().size(), 1);
}
diff --git a/sources/shiboken6/ApiExtractor/textstream.h b/sources/shiboken6/ApiExtractor/textstream.h
index 074e23858..228f36405 100644
--- a/sources/shiboken6/ApiExtractor/textstream.h
+++ b/sources/shiboken6/ApiExtractor/textstream.h
@@ -31,7 +31,7 @@ public:
virtual ~TextStream();
Language language() const { return m_language; }
- void setLanguage(const Language &language) { m_language = language; }
+ void setLanguage(Language language) { m_language = language; }
bool isIndentationEnabled() const { return m_indentationEnabled; }
void setIndentationEnabled(bool m)
@@ -77,6 +77,10 @@ public:
void putRawChar(char c) { m_str << c; }
TextStream &operator<<(QStringView v) { putString(v); return *this; }
+ TextStream &operator<<(const QString &qs) { putString(QStringView{qs}); return *this; }
+ TextStream &operator<<(QLatin1StringView lv) { putString(lv.constData()); return *this; }
+ TextStream &operator<<(QUtf8StringView uv) { putString(uv.data()); return *this; }
+ TextStream &operator<<(const QByteArray &ba) { putString(ba.constData()); return *this; }
TextStream &operator<<(QChar c) { putChar(c); return *this; }
TextStream &operator<<(const char *s) { putString(s); return *this; }
TextStream &operator<<(char c) { putChar(c); return *this; }
@@ -85,7 +89,7 @@ public:
TextStream &operator<<(qsizetype t) { putSizeType(t); return *this; }
#endif
- inline TextStream &operator<<(QTextStreamManipulator m) { m_str << m; return *this; }
+ inline TextStream &operator<<(const QTextStreamManipulator &m) { m_str << m; return *this; }
inline TextStream &operator<<(ManipulatorFunc f) { f(*this); return *this; }
void putRepetitiveChars(char c, int count);
@@ -140,6 +144,12 @@ void rstCodeOff(TextStream &s);
void rstItalic(TextStream &s);
void rstItalicOff(TextStream &s);
+inline TextStream &operator<<(TextStream &str, QAnyStringView asv)
+{
+ asv.visit([&str](auto s) { str << s; });
+ return str;
+}
+
/// Format an aligned field
template <class T>
class AlignedField
@@ -179,6 +189,28 @@ TextStream &operator<<(TextStream &str, const AlignedField<T> &fa)
return str;
}
+class Pad
+{
+public:
+ explicit Pad(char c, int count) : m_char(c), m_count(count) {}
+
+ void write(TextStream &str) const
+ {
+ for (int i = 0; i < m_count; ++i)
+ str << m_char;
+ }
+
+private:
+ const char m_char;
+ const int m_count;
+};
+
+inline TextStream &operator<<(TextStream &str, const Pad &pad)
+{
+ pad.write(str);
+ return str;
+}
+
class Indentation
{
public:
diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp
index 22d558cc2..749c4baa3 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp
@@ -3,28 +3,25 @@
#include "typedatabase.h"
#include "abstractmetatype.h"
-#include "exception.h"
+#include "addedfunction.h"
#include "messages.h"
#include "typesystemparser_p.h"
-#include "arraytypeentry.h"
#include "complextypeentry.h"
#include "constantvaluetypeentry.h"
#include "containertypeentry.h"
-#include "customconversion.h"
#include "customtypenentry.h"
-#include "enumtypeentry.h"
-#include "enumvaluetypeentry.h"
+#include "debughelpers_p.h"
+#include "exception.h"
#include "flagstypeentry.h"
#include "functiontypeentry.h"
#include "namespacetypeentry.h"
#include "objecttypeentry.h"
#include "primitivetypeentry.h"
+#include "optionsparser.h"
#include "pythontypeentry.h"
#include "smartpointertypeentry.h"
-#include "templateargumententry.h"
#include "typedefentry.h"
#include "typesystemtypeentry.h"
-#include "valuetypeentry.h"
#include "varargstypeentry.h"
#include "voidtypeentry.h"
#include "conditionalstreamreader.h"
@@ -38,29 +35,29 @@
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <QtCore/QDir>
-#include <QtCore/QPair>
#include <QtCore/QList>
#include <QtCore/QRegularExpression>
#include <QtCore/QVersionNumber>
#include <QtCore/QXmlStreamReader>
#include "reporthandler.h"
-// #include <tr1/tuple>
+
#include <algorithm>
+#include <utility>
using namespace Qt::StringLiterals;
-using TypeDatabaseParserContextPtr = QSharedPointer<TypeDatabaseParserContext>;
+using TypeDatabaseParserContextPtr = std::shared_ptr<TypeDatabaseParserContext>;
// package -> api-version
static QString wildcardToRegExp(QString w)
{
w.replace(u'?', u'.');
- w.replace(u'*', QStringLiteral(".*"));
+ w.replace(u'*', ".*"_L1);
return w;
}
-using ApiVersion =QPair<QRegularExpression, QVersionNumber>;
+using ApiVersion = std::pair<QRegularExpression, QVersionNumber>;
using ApiVersions = QList<ApiVersion>;
Q_GLOBAL_STATIC(ApiVersions, apiVersions)
@@ -106,12 +103,132 @@ static const PythonTypes &builtinPythonTypes()
return result;
}
-struct TypeDatabasePrivate
+struct SuppressedWarning
+{
+ QRegularExpression pattern;
+ QString rawText;
+ bool generate; // Current type system
+ mutable bool matched = false;
+};
+
+QList<OptionDescription> TypeDatabase::options()
+{
+ return {
+ {u"api-version=<\"package mask\">,<\"version\">"_s,
+ u"Specify the supported api version used to generate the bindings"_s},
+ {u"drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""_s,
+ u"Semicolon separated list of type system entries (classes, namespaces,\n"
+ "global functions and enums) to be dropped from generation."_s},
+ {u"-T<path>"_s, {} },
+ {u"typesystem-paths="_s + OptionsParser::pathSyntax(),
+ u"Paths used when searching for typesystems"_s},
+ {u"force-process-system-include-paths="_s + OptionsParser::pathSyntax(),
+ u"Include paths that are considered as system headers by the C++ parser, but should still "
+ "be processed to extract types (e.g. Qt include paths in a yocto sysroot)"_s},
+ {u"keywords=keyword1[,keyword2,...]"_s,
+ u"A comma-separated list of keywords for conditional typesystem parsing"_s},
+ };
+}
+
+struct TypeDatabaseOptions
{
- const TypeSystemTypeEntry *defaultTypeSystemType() const;
- TypeEntry *findType(const QString &name) const;
- TypeEntries findCppTypes(const QString &name) const;
- bool addType(TypeEntry *e, QString *errorMessage = nullptr);
+ QStringList m_dropTypeEntries;
+ QStringList m_forceProcessSystemIncludes;
+ QStringList m_typesystemKeywords;
+ QStringList m_typesystemPaths;
+ bool m_suppressWarnings = true;
+};
+
+class TypeDatabaseOptionsParser : public OptionsParser
+{
+public:
+ explicit TypeDatabaseOptionsParser(TypeDatabaseOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value, OptionSource source) override;
+
+private:
+ TypeDatabaseOptions *m_options;
+};
+
+bool TypeDatabaseOptionsParser::handleBoolOption(const QString &key, OptionSource source)
+{
+ switch (source) {
+ case OptionSource::CommandLine:
+ case OptionSource::ProjectFile:
+ if (key == u"no-suppress-warnings") {
+ m_options->m_suppressWarnings = false;
+ return true;
+ }
+ break;
+ case OptionSource::CommandLineSingleDash:
+ if (key.startsWith(u'T')) { // "-T/path" ends up a bool option
+ m_options->m_typesystemPaths += key.sliced(1).split(QDir::listSeparator(),
+ Qt::SkipEmptyParts);
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool TypeDatabaseOptionsParser::handleOption(const QString &key, const QString &value,
+ OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
+ if (key == u"api-version") {
+ const auto fullVersions = QStringView{value}.split(u'|');
+ for (const auto &fullVersion : fullVersions) {
+ const auto parts = fullVersion.split(u',');
+ const QString package = parts.size() == 1
+ ? u"*"_s : parts.constFirst().toString();
+ const QString version = parts.constLast().toString();
+ if (!TypeDatabase::setApiVersion(package, version))
+ throw Exception(msgInvalidVersion(package, version));
+ }
+ return true;
+ }
+
+ if (key == u"drop-type-entries") {
+ m_options->m_dropTypeEntries = value.split(u';');
+ m_options->m_dropTypeEntries.sort();
+ return true;
+ }
+
+ if (key == u"keywords") {
+ m_options->m_typesystemKeywords = value.split(u',');
+ return true;
+ }
+
+ if (key == u"typesystem-paths") {
+ m_options->m_typesystemPaths += value.split(QDir::listSeparator(),
+ Qt::SkipEmptyParts);
+ return true;
+ }
+
+ if (key == u"force-process-system-include-paths") {
+ m_options->m_forceProcessSystemIncludes += value.split(QDir::listSeparator(),
+ Qt::SkipEmptyParts);
+ return true;
+ }
+
+ if (source == OptionSource::ProjectFile) {
+ if (key == u"typesystem-path") {
+ m_options->m_typesystemPaths += value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+struct TypeDatabasePrivate : public TypeDatabaseOptions
+{
+ TypeSystemTypeEntryCPtr defaultTypeSystemType() const;
+ TypeEntryPtr findType(const QString &name) const;
+ TypeEntryCList findCppTypes(const QString &name) const;
+ bool addType(TypeEntryPtr e, QString *errorMessage = nullptr);
bool parseFile(QIODevice *device, TypeDatabase *db, bool generate = true);
static bool parseFile(const TypeDatabaseParserContextPtr &context,
QIODevice *device, bool generate = true);
@@ -122,58 +239,63 @@ struct TypeDatabasePrivate
QString modifiedTypesystemFilepath(const QString& tsFile,
const QString &currentPath) const;
- void addBuiltInType(TypeEntry *e);
- PrimitiveTypeEntry *addBuiltInPrimitiveType(const QString &name,
- const TypeSystemTypeEntry *root,
+ void addBuiltInType(const TypeEntryPtr &e);
+ PrimitiveTypeEntryPtr addBuiltInPrimitiveType(const QString &name,
+ const TypeSystemTypeEntryCPtr &root,
const QString &rootPackage,
- CustomTypeEntry *targetLang);
+ const CustomTypeEntryPtr &targetLang);
void addBuiltInCppStringPrimitiveType(const QString &name,
const QString &viewName,
- const TypeSystemTypeEntry *root,
+ const TypeSystemTypeEntryCPtr &root,
const QString &rootPackage,
- CustomTypeEntry *targetLang);
+ const CustomTypeEntryPtr &targetLang);
void addBuiltInPrimitiveTypes();
void addBuiltInContainerTypes(const TypeDatabaseParserContextPtr &context);
+ bool addOpaqueContainers(const TypeDatabaseParserContextPtr &context);
TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const;
template <class Predicate>
- TypeEntries findTypesHelper(const QString &name, Predicate pred) const;
+ TypeEntryCList findTypesHelper(const QString &name, Predicate pred) const;
template <class Type, class Predicate>
- QList<const Type *> findTypesByTypeHelper(Predicate pred) const;
- TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage);
+ QList<std::shared_ptr<const Type> > findTypesByTypeHelper(Predicate pred) const;
+ TypeEntryPtr resolveTypeDefEntry(const TypedefEntryPtr &typedefEntry, QString *errorMessage);
template <class String>
bool isSuppressedWarningHelper(const String &s) const;
bool resolveSmartPointerInstantiations(const TypeDatabaseParserContextPtr &context);
void formatDebug(QDebug &d) const;
+ void formatBuiltinTypes(QDebug &d) const;
- bool m_suppressWarnings = true;
TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups).
TypeEntryMap m_flagsEntries;
TypedefEntryMap m_typedefEntries;
TemplateEntryMap m_templates;
- QList<QRegularExpression> m_suppressedWarnings;
- QList<const TypeSystemTypeEntry *> m_typeSystemEntries; // maintain order, default is first.
+ QList<SuppressedWarning> m_suppressedWarnings;
+ QList<TypeSystemTypeEntryCPtr > m_typeSystemEntries; // maintain order, default is first.
AddedFunctionList m_globalUserFunctions;
FunctionModificationList m_functionMods;
QStringList m_requiredTargetImports;
- QStringList m_typesystemPaths;
- QStringList m_typesystemKeywords;
QHash<QString, bool> m_parsedTypesystemFiles;
QList<TypeRejection> m_rejections;
-
- QStringList m_dropTypeEntries;
- QStringList m_systemIncludes;
};
+static const char ENV_TYPESYSTEMPATH[] = "TYPESYSTEMPATH";
+
TypeDatabase::TypeDatabase() : d(new TypeDatabasePrivate)
{
- d->addBuiltInType(new VoidTypeEntry());
- d->addBuiltInType(new VarargsTypeEntry());
+ // Environment TYPESYSTEMPATH
+ if (qEnvironmentVariableIsSet(ENV_TYPESYSTEMPATH)) {
+ d->m_typesystemPaths
+ += qEnvironmentVariable(ENV_TYPESYSTEMPATH).split(QDir::listSeparator(),
+ Qt::SkipEmptyParts);
+ }
+
+ d->addBuiltInType(TypeEntryPtr(new VoidTypeEntry()));
+ d->addBuiltInType(TypeEntryPtr(new VarargsTypeEntry()));
for (const auto &pt : builtinPythonTypes())
- d->addBuiltInType(new PythonTypeEntry(pt.name, pt.checkFunction, pt.type));
+ d->addBuiltInType(TypeEntryPtr(new PythonTypeEntry(pt.name, pt.checkFunction, pt.type)));
for (const auto &p : predefinedTemplates())
addTemplate(p.name, p.content);
@@ -184,7 +306,12 @@ TypeDatabase::~TypeDatabase()
delete d;
}
-TypeDatabase* TypeDatabase::instance(bool newInstance)
+std::shared_ptr<OptionsParser> TypeDatabase::createOptionsParser()
+{
+ return std::make_shared<TypeDatabaseOptionsParser>(d);
+}
+
+TypeDatabase *TypeDatabase::instance(bool newInstance)
{
static TypeDatabase *db = nullptr;
if (!db || newInstance) {
@@ -210,12 +337,11 @@ static const IntTypeNormalizationEntries &intTypeNormalizationEntries()
static bool firstTime = true;
if (firstTime) {
firstTime = false;
- for (auto t : {"char", "short", "int", "long"}) {
- const QString intType = QLatin1StringView(t);
+ for (const auto &intType : {"char"_L1, "short"_L1, "int"_L1, "long"_L1}) {
if (!TypeDatabase::instance()->findType(u'u' + intType)) {
IntTypeNormalizationEntry entry;
- entry.replacement = QStringLiteral("unsigned ") + intType;
- entry.regex.setPattern(QStringLiteral("\\bu") + intType + QStringLiteral("\\b"));
+ entry.replacement = "unsigned "_L1 + intType;
+ entry.regex.setPattern("\\bu"_L1 + intType + "\\b"_L1);
Q_ASSERT(entry.regex.isValid());
result.append(entry);
}
@@ -301,26 +427,11 @@ void TypeDatabase::addRequiredTargetImport(const QString& moduleName)
d->m_requiredTargetImports << moduleName;
}
-void TypeDatabase::addTypesystemPath(const QString& typesystem_paths)
-{
- #if defined(Q_OS_WIN32)
- const char path_splitter = ';';
- #else
- const char path_splitter = ':';
- #endif
- d->m_typesystemPaths += typesystem_paths.split(QLatin1Char(path_splitter));
-}
-
-void TypeDatabase::setTypesystemKeywords(const QStringList &keywords)
-{
- d->m_typesystemKeywords = keywords;
-}
-
QStringList TypeDatabase::typesystemKeywords() const
{
QStringList result = d->m_typesystemKeywords;
for (const auto &d : d->m_dropTypeEntries)
- result.append(QStringLiteral("no_") + d);
+ result.append("no_"_L1 + d);
switch (clang::emulatedCompilerLanguageLevel()) {
case LanguageLevel::Cpp11:
@@ -343,84 +454,95 @@ QStringList TypeDatabase::typesystemKeywords() const
IncludeList TypeDatabase::extraIncludes(const QString& className) const
{
- ComplexTypeEntry* typeEntry = findComplexType(className);
- return typeEntry ? typeEntry->extraIncludes() : IncludeList();
+ auto typeEntry = findComplexType(className);
+ return typeEntry ? typeEntry->extraIncludes() : IncludeList();
}
-const QStringList &TypeDatabase::systemIncludes() const
+const QStringList &TypeDatabase::forceProcessSystemIncludes() const
{
- return d->m_systemIncludes;
+ return d->m_forceProcessSystemIncludes;
}
-void TypeDatabase::addSystemInclude(const QString &name)
+void TypeDatabase::addForceProcessSystemInclude(const QString &name)
{
- d->m_systemIncludes.append(name);
+ d->m_forceProcessSystemIncludes.append(name);
}
// Add a lookup for the short name excluding inline namespaces
// so that "std::shared_ptr" finds "std::__1::shared_ptr" as well.
-// Note: This inserts duplicate TypeEntry * into m_entries.
-void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntry *n)
+// Note: This inserts duplicate TypeEntryPtr into m_entries.
+void TypeDatabase::addInlineNamespaceLookups(const NamespaceTypeEntryCPtr &n)
{
TypeEntryList additionalEntries; // Store before modifying the hash
- for (TypeEntry *entry : qAsConst(d->m_entries)) {
+ for (const auto &entry : std::as_const(d->m_entries)) {
if (entry->isChildOf(n))
additionalEntries.append(entry);
}
- for (const auto &ae : qAsConst(additionalEntries))
+ for (const auto &ae : std::as_const(additionalEntries))
d->m_entries.insert(ae->shortName(), ae);
}
-ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const
+ContainerTypeEntryPtr TypeDatabase::findContainerType(const QString &name) const
{
QString template_name = name;
- int pos = name.indexOf(u'<');
+ const auto pos = name.indexOf(u'<');
if (pos > 0)
template_name = name.left(pos);
- TypeEntry* type_entry = findType(template_name);
+ auto type_entry = findType(template_name);
if (type_entry && type_entry->isContainer())
- return static_cast<ContainerTypeEntry*>(type_entry);
- return nullptr;
+ return std::static_pointer_cast<ContainerTypeEntry>(type_entry);
+ return {};
}
-static bool inline useType(const TypeEntry *t)
+static bool inline useType(const TypeEntryCPtr &t)
{
return !t->isPrimitive()
- || static_cast<const PrimitiveTypeEntry *>(t)->preferredTargetLangType();
+ || std::static_pointer_cast<const PrimitiveTypeEntry>(t)->preferredTargetLangType();
}
-FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const
+FunctionTypeEntryPtr TypeDatabase::findFunctionType(const QString &name) const
{
const auto entries = d->findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const TypeEntryPtr &entry : entries) {
if (entry->type() == TypeEntry::FunctionType && useType(entry))
- return static_cast<FunctionTypeEntry*>(entry);
+ return std::static_pointer_cast<FunctionTypeEntry>(entry);
}
- return nullptr;
+ return {};
}
-void TypeDatabase::addTypeSystemType(const TypeSystemTypeEntry *e)
+void TypeDatabase::addTypeSystemType(const TypeSystemTypeEntryCPtr &e)
{
d->m_typeSystemEntries.append(e);
}
-const TypeSystemTypeEntry *TypeDatabase::findTypeSystemType(const QString &name) const
+TypeSystemTypeEntryCPtr TypeDatabase::findTypeSystemType(const QString &name) const
{
for (auto entry : d->m_typeSystemEntries) {
if (entry->name() == name)
return entry;
}
- return nullptr;
+ return {};
}
-const TypeSystemTypeEntry *TypeDatabase::defaultTypeSystemType() const
+TypeSystemTypeEntryCPtr TypeDatabase::defaultTypeSystemType() const
{
return d->defaultTypeSystemType();
}
-const TypeSystemTypeEntry *TypeDatabasePrivate::defaultTypeSystemType() const
+QString TypeDatabase::loadedTypeSystemNames() const
+{
+ QString result;
+ for (const auto &entry : d->m_typeSystemEntries) {
+ if (!result.isEmpty())
+ result += u", "_s;
+ result += entry->name();
+ }
+ return result;
+}
+
+TypeSystemTypeEntryCPtr TypeDatabasePrivate::defaultTypeSystemType() const
{
return m_typeSystemEntries.value(0, nullptr);
}
@@ -431,27 +553,27 @@ QString TypeDatabase::defaultPackageName() const
return d->m_typeSystemEntries.constFirst()->name();
}
-TypeEntry* TypeDatabase::findType(const QString& name) const
+TypeEntryPtr TypeDatabase::findType(const QString& name) const
{
return d->findType(name);
}
-TypeEntry* TypeDatabasePrivate::findType(const QString& name) const
+TypeEntryPtr TypeDatabasePrivate::findType(const QString& name) const
{
const auto entries = findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (useType(entry))
return entry;
}
- return nullptr;
+ return {};
}
template <class Predicate>
-TypeEntries TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate pred) const
+TypeEntryCList TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate pred) const
{
- TypeEntries result;
+ TypeEntryCList result;
const auto entries = findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (pred(entry))
result.append(entry);
}
@@ -459,22 +581,22 @@ TypeEntries TypeDatabasePrivate::findTypesHelper(const QString &name, Predicate
}
template<class Type, class Predicate>
-QList<const Type *> TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const
+QList<std::shared_ptr<const Type> > TypeDatabasePrivate::findTypesByTypeHelper(Predicate pred) const
{
- QList<const Type *> result;
- for (auto *entry : m_entries) {
+ QList<std::shared_ptr<const Type> > result;
+ for (const auto &entry : m_entries) {
if (pred(entry))
- result.append(static_cast<const Type *>(entry));
+ result.append(std::static_pointer_cast<const Type>(entry));
}
return result;
}
-TypeEntries TypeDatabase::findTypes(const QString &name) const
+TypeEntryCList TypeDatabase::findTypes(const QString &name) const
{
return d->findTypesHelper(name, useType);
}
-static bool useCppType(const TypeEntry *t)
+static bool useCppType(const TypeEntryCPtr &t)
{
bool result = false;
switch (t->type()) {
@@ -498,12 +620,12 @@ static bool useCppType(const TypeEntry *t)
return result;
}
-TypeEntries TypeDatabase::findCppTypes(const QString &name) const
+TypeEntryCList TypeDatabase::findCppTypes(const QString &name) const
{
return d->findCppTypes(name);
}
-TypeEntries TypeDatabasePrivate::findCppTypes(const QString &name) const
+TypeEntryCList TypeDatabasePrivate::findCppTypes(const QString &name) const
{
return findTypesHelper(name, useCppType);
}
@@ -524,21 +646,21 @@ TypeEntryMultiMapConstIteratorRange TypeDatabasePrivate::findTypeRange(const QSt
return {range.first, range.second};
}
-PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const
+PrimitiveTypeEntryCList TypeDatabase::primitiveTypes() const
{
- auto pred = [](const TypeEntry *t) { return t->isPrimitive(); };
+ auto pred = [](const TypeEntryCPtr &t) { return t->isPrimitive(); };
return d->findTypesByTypeHelper<PrimitiveTypeEntry>(pred);
}
-ContainerTypeEntryList TypeDatabase::containerTypes() const
+ContainerTypeEntryCList TypeDatabase::containerTypes() const
{
- auto pred = [](const TypeEntry *t) { return t->isContainer(); };
+ auto pred = [](const TypeEntryCPtr &t) { return t->isContainer(); };
return d->findTypesByTypeHelper<ContainerTypeEntry>(pred);
}
SmartPointerTypeEntryList TypeDatabase::smartPointerTypes() const
{
- auto pred = [](const TypeEntry *t) { return t->isSmartPointer(); };
+ auto pred = [](const TypeEntryCPtr &t) { return t->isSmartPointer(); };
return d->findTypesByTypeHelper<SmartPointerTypeEntry>(pred);
}
@@ -564,6 +686,7 @@ bool TypeDatabase::isClassRejected(const QString& className, QString *reason) co
{
for (const TypeRejection& r : d->m_rejections) {
if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) {
+ r.matched = true;
if (reason)
*reason = msgRejectReason(r);
return true;
@@ -582,6 +705,7 @@ static bool findRejection(const QList<TypeRejection> &rejections,
for (const TypeRejection& r : rejections) {
if (r.matchType == matchType && r.pattern.match(name).hasMatch()
&& r.className.match(className).hasMatch()) {
+ r.matched = true;
if (reason)
*reason = msgRejectReason(r, name);
return true;
@@ -595,21 +719,21 @@ bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumN
return findRejection(d->m_rejections, TypeRejection::Enum, className, enumName, reason);
}
-TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry,
+TypeEntryPtr TypeDatabasePrivate::resolveTypeDefEntry(const TypedefEntryPtr &typedefEntry,
QString *errorMessage)
{
QString sourceName = typedefEntry->sourceType();
- const int lessThanPos = sourceName.indexOf(u'<');
+ const auto lessThanPos = sourceName.indexOf(u'<');
if (lessThanPos != -1)
sourceName.truncate(lessThanPos);
- ComplexTypeEntry *source = nullptr;
- for (TypeEntry *e : findTypeRange(sourceName)) {
+ ComplexTypeEntryPtr source;
+ for (const auto &e : findTypeRange(sourceName)) {
switch (e->type()) {
case TypeEntry::BasicValueType:
case TypeEntry::ContainerType:
case TypeEntry::ObjectType:
case TypeEntry::SmartPointerType:
- source = dynamic_cast<ComplexTypeEntry *>(e);
+ source = std::dynamic_pointer_cast<ComplexTypeEntry>(e);
Q_ASSERT(source);
break;
default:
@@ -618,8 +742,7 @@ TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry,
}
if (!source) {
if (errorMessage)
- *errorMessage = u"Unable to resolve typedef \""_s
- + typedefEntry->sourceType() + u'"';
+ *errorMessage = msgUnableToResolveTypedef(typedefEntry->sourceType(), sourceName);
return nullptr;
}
@@ -627,26 +750,26 @@ TypeEntry *TypeDatabasePrivate::resolveTypeDefEntry(TypedefEntry *typedefEntry,
return TypeDatabase::initializeTypeDefEntry(typedefEntry, source);
}
-ComplexTypeEntry *
- TypeDatabase::initializeTypeDefEntry(TypedefEntry *typedefEntry,
- const ComplexTypeEntry *source)
+ComplexTypeEntryPtr
+ TypeDatabase::initializeTypeDefEntry(const TypedefEntryPtr &typedefEntry,
+ const ComplexTypeEntryCPtr &source)
{
- auto *result = static_cast<ComplexTypeEntry *>(source->clone());
+ ComplexTypeEntryPtr result(static_cast<ComplexTypeEntry *>(source->clone()));
result->useAsTypedef(typedefEntry);
typedefEntry->setSource(source);
typedefEntry->setTarget(result);
return result;
}
-bool TypeDatabase::addType(TypeEntry *e, QString *errorMessage)
+bool TypeDatabase::addType(const TypeEntryPtr &e, QString *errorMessage)
{
return d->addType(e, errorMessage);
}
-bool TypeDatabasePrivate::addType(TypeEntry *e, QString *errorMessage)
+bool TypeDatabasePrivate::addType(TypeEntryPtr e, QString *errorMessage)
{
if (e->type() == TypeEntry::TypedefType) {
- e = resolveTypeDefEntry(static_cast<TypedefEntry *>(e), errorMessage);
+ e = resolveTypeDefEntry(std::static_pointer_cast<TypedefEntry>(e), errorMessage);
if (Q_UNLIKELY(!e))
return false;
}
@@ -655,11 +778,11 @@ bool TypeDatabasePrivate::addType(TypeEntry *e, QString *errorMessage)
}
// Add a dummy value entry for non-type template parameters
-ConstantValueTypeEntry *
+ConstantValueTypeEntryPtr
TypeDatabase::addConstantValueTypeEntry(const QString &value,
- const TypeEntry *parent)
+ const TypeEntryCPtr &parent)
{
- auto result = new ConstantValueTypeEntry(value, parent);
+ auto result = std::make_shared<ConstantValueTypeEntry>(value, parent);
result->setCodeGeneration(TypeEntry::GenerateNothing);
addType(result);
return result;
@@ -689,9 +812,9 @@ bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString&
return findRejection(d->m_rejections, TypeRejection::ReturnType, className, typeName, reason);
}
-FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const
+FlagsTypeEntryPtr TypeDatabase::findFlagsType(const QString &name) const
{
- TypeEntry *fte = findType(name);
+ TypeEntryPtr fte = findType(name);
if (!fte) {
fte = d->m_flagsEntries.value(name);
if (!fte) {
@@ -705,27 +828,27 @@ FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const
}
}
}
- return static_cast<FlagsTypeEntry *>(fte);
+ return std::static_pointer_cast<FlagsTypeEntry>(fte);
}
-void TypeDatabase::addFlagsType(FlagsTypeEntry *fte)
+void TypeDatabase::addFlagsType(const FlagsTypeEntryPtr &fte)
{
d->m_flagsEntries[fte->originalName()] = fte;
}
-TemplateEntry *TypeDatabase::findTemplate(const QString &name) const
+TemplateEntryPtr TypeDatabase::findTemplate(const QString &name) const
{
return d->m_templates[name];
}
-void TypeDatabase::addTemplate(TemplateEntry *t)
+void TypeDatabase::addTemplate(const TemplateEntryPtr &t)
{
d->m_templates[t->name()] = t;
}
void TypeDatabase::addTemplate(const QString &name, const QString &code)
{
- auto *te = new TemplateEntry(name);
+ auto te = std::make_shared<TemplateEntry>(name);
te->addCode(code);
addTemplate(te);
}
@@ -755,37 +878,34 @@ void TypeDatabase::addGlobalUserFunctionModifications(const FunctionModification
d->m_functionMods << functionModifications;
}
-QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/)
+QString TypeDatabase::globalNamespaceClassName(const TypeEntryCPtr & /*entry*/)
{
return u"Global"_s;
}
-FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const
+FunctionModificationList
+ TypeDatabase::globalFunctionModifications(const QStringList &signatures) const
{
FunctionModificationList lst;
for (const auto &mod : d->m_functionMods) {
- if (mod.matches(signature))
+ if (mod.matches(signatures))
lst << mod;
}
return lst;
}
-void TypeDatabase::setSuppressWarnings(bool on)
-{
- d->m_suppressWarnings = on;
-}
-
-bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMessage)
+bool TypeDatabase::addSuppressedWarning(const QString &warning, bool generate,
+ QString *errorMessage)
{
QString pattern;
if (warning.startsWith(u'^') && warning.endsWith(u'$')) {
pattern = warning;
} else {
// Legacy syntax: Use wildcards '*' (unless escaped by '\')
- QList<int> asteriskPositions;
- const int warningSize = warning.size();
- for (int i = 0; i < warningSize; ++i) {
+ QList<qsizetype> asteriskPositions;
+ const auto warningSize = warning.size();
+ for (qsizetype i = 0, warningSize = warning.size(); i < warningSize; ++i) {
if (warning.at(i) == u'\\')
++i;
else if (warning.at(i) == u'*')
@@ -794,11 +914,11 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe
asteriskPositions.append(warningSize);
pattern.append(u'^');
- int lastPos = 0;
- for (int a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) {
+ qsizetype lastPos = 0;
+ for (qsizetype a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) {
if (a)
- pattern.append(QStringLiteral(".*"));
- const int nextPos = asteriskPositions.at(a);
+ pattern.append(".*"_L1);
+ const auto nextPos = asteriskPositions.at(a);
if (nextPos > lastPos)
pattern.append(QRegularExpression::escape(warning.mid(lastPos, nextPos - lastPos)));
lastPos = nextPos + 1;
@@ -814,7 +934,7 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe
}
expression.setPatternOptions(expression.patternOptions() | QRegularExpression::MultilineOption);
- d->m_suppressedWarnings.append(expression);
+ d->m_suppressedWarnings.append({expression, warning, generate});
return true;
}
@@ -822,10 +942,14 @@ bool TypeDatabase::isSuppressedWarning(QStringView s) const
{
if (!d->m_suppressWarnings)
return false;
- return std::any_of(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(),
- [&s] (const QRegularExpression &e) {
- return e.match(s).hasMatch();
- });
+ auto wit = std::find_if(d->m_suppressedWarnings.cbegin(), d->m_suppressedWarnings.cend(),
+ [&s] (const SuppressedWarning &e) {
+ return e.pattern.matchView(s).hasMatch();
+ });
+ const bool found = wit != d->m_suppressedWarnings.cend();
+ if (found)
+ wit->matched = true;
+ return found;
}
QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString &currentPath) const
@@ -833,6 +957,27 @@ QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QS
return d->modifiedTypesystemFilepath(tsFile, currentPath);
}
+void TypeDatabase::logUnmatched() const
+{
+ for (auto &sw : d->m_suppressedWarnings) {
+ if (sw.generate && !sw.matched)
+ qWarning("Unmatched suppressed warning: \"%s\"", qPrintable(sw.rawText));
+ }
+
+ for (auto &tr : d->m_rejections) {
+ if (tr.generate && !tr.matched) {
+ QDebug d = qWarning();
+ d.noquote();
+ d.nospace();
+ d << "Unmatched rejection: " << tr.matchType;
+ if (!tr.className.pattern().isEmpty())
+ d << " class " << tr.className.pattern();
+ if (!tr.pattern.pattern().isEmpty())
+ d << " \"" << tr.pattern.pattern() << '"';
+ }
+ }
+}
+
QString TypeDatabasePrivate::modifiedTypesystemFilepath(const QString& tsFile,
const QString &currentPath) const
{
@@ -858,16 +1003,25 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
{
// Unless the user has added the standard containers (potentially with
// some opaque types), add them by default.
+ const bool hasStdArray = findType(u"std::array"_s) != nullptr;
const bool hasStdPair = findType(u"std::pair"_s) != nullptr;
const bool hasStdList = findType(u"std::list"_s) != nullptr;
const bool hasStdVector = findType(u"std::vector"_s) != nullptr;
const bool hasStdMap = findType(u"std::map"_s) != nullptr;
const bool hasStdUnorderedMap = findType(u"std::unordered_map"_s) != nullptr;
+ const bool hasStdSpan = findType(u"std::span"_s) != nullptr;
if (hasStdPair && hasStdList && hasStdVector && hasStdMap && hasStdUnorderedMap)
return;
QByteArray ts = R"(<?xml version="1.0" encoding="UTF-8"?><typesystem>)";
+ if (!hasStdArray) {
+ ts += containerTypeSystemSnippet(
+ "std::array", "list", "array",
+ "shiboken_conversion_cppsequence_to_pylist",
+ "PySequence",
+ "shiboken_conversion_pyiterable_to_cpparray");
+ }
if (!hasStdPair) {
ts += containerTypeSystemSnippet(
"std::pair", "pair", "utility",
@@ -900,6 +1054,16 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
"shiboken_conversion_stdmap_to_pydict",
"PyDict", "shiboken_conversion_pydict_to_stdmap");
}
+ if (!hasStdSpan
+ && clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20) {
+ auto spanSnip = containerTypeSystemSnippet(
+ "std::span", "span", "span",
+ "shiboken_conversion_cppsequence_to_pylist");
+ auto pos = spanSnip.indexOf('>');
+ spanSnip.insert(pos, R"( view-on="std::vector")");
+ ts += spanSnip;
+ }
+
ts += "</typesystem>";
QBuffer buffer(&ts);
buffer.open(QIODevice::ReadOnly);
@@ -907,6 +1071,22 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
Q_ASSERT(ok);
}
+bool TypeDatabasePrivate::addOpaqueContainers(const TypeDatabaseParserContextPtr &context)
+{
+ const auto &och = context->opaqueContainerHash;
+ for (auto it = och.cbegin(), end = och.cend(); it != end; ++it) {
+ const QString &name = it.key();
+ auto te = findType(name);
+ if (!te || !te->isContainer()) {
+ qCWarning(lcShiboken, "No container \"%s\" found.", qPrintable(name));
+ return false;
+ }
+ auto cte = std::static_pointer_cast<ContainerTypeEntry>(te);
+ cte->appendOpaqueContainers(it.value());
+ }
+ return true;
+}
+
bool TypeDatabase::parseFile(const QString &filename, bool generate)
{
QString filepath = modifiedTypesystemFilepath(filename, {});
@@ -963,14 +1143,14 @@ bool TypeDatabasePrivate::parseFile(const TypeDatabaseParserContextPtr &context,
return ok;
}
-bool TypeDatabase::parseFile(QIODevice* device, bool generate)
+bool TypeDatabase::parseFile(QIODevice *device, bool generate)
{
return d->parseFile(device, this, generate);
}
-bool TypeDatabasePrivate::parseFile(QIODevice* device, TypeDatabase *db, bool generate)
+bool TypeDatabasePrivate::parseFile(QIODevice *device, TypeDatabase *db, bool generate)
{
- const TypeDatabaseParserContextPtr context(new TypeDatabaseParserContext);
+ const auto context = std::make_shared<TypeDatabaseParserContext>();
context->db = db;
if (!parseFile(context, device, generate))
@@ -978,7 +1158,8 @@ bool TypeDatabasePrivate::parseFile(QIODevice* device, TypeDatabase *db, bool ge
addBuiltInPrimitiveTypes();
addBuiltInContainerTypes(context);
- return resolveSmartPointerInstantiations(context);
+ return addOpaqueContainers(context)
+ && resolveSmartPointerInstantiations(context);
}
bool TypeDatabase::parseFile(const TypeDatabaseParserContextPtr &context,
@@ -1007,9 +1188,9 @@ static QStringList splitTypeList(const QString &s)
{
QStringList result;
int templateDepth = 0;
- int lastPos = 0;
- const int size = s.size();
- for (int i = 0; i < size; ++i) {
+ qsizetype lastPos = 0;
+ const auto size = s.size();
+ for (qsizetype i = 0; i < size; ++i) {
switch (s.at(i).toLatin1()) {
case '<':
++templateDepth;
@@ -1038,32 +1219,40 @@ bool TypeDatabasePrivate::resolveSmartPointerInstantiations(const TypeDatabasePa
const auto instantiationNames = splitTypeList(it.value());
SmartPointerTypeEntry::Instantiations instantiations;
instantiations.reserve(instantiationNames.size());
- for (const auto &instantiationName : instantiationNames) {
- const auto types = findCppTypes(instantiationName);
- if (types.isEmpty()) {
- const QString m = msgCannotFindTypeEntryForSmartPointer(instantiationName,
+ for (const auto &instantiation : instantiationNames) {
+ QString name;
+ QString type = instantiation;
+ const auto equalsPos = instantiation.indexOf(u'=');
+ if (equalsPos != -1) {
+ type.truncate(equalsPos);
+ name = instantiation.mid(equalsPos + 1);
+ }
+
+ const auto typeEntries = findCppTypes(type);
+ if (typeEntries.isEmpty()) {
+ const QString m = msgCannotFindTypeEntryForSmartPointer(type,
smartPointerEntry->name());
qCWarning(lcShiboken, "%s", qPrintable(m));
return false;
}
- if (types.size() > 1) {
- const QString m = msgAmbiguousTypesFound(instantiationName, types);
+ if (typeEntries.size() > 1) {
+ const QString m = msgAmbiguousTypesFound(type, typeEntries);
qCWarning(lcShiboken, "%s", qPrintable(m));
return false;
}
- instantiations.append(types.constFirst());
+ instantiations.append({name, typeEntries.constFirst()});
}
smartPointerEntry->setInstantiations(instantiations);
}
return true;
}
-PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const
+PrimitiveTypeEntryPtr TypeDatabase::findPrimitiveType(const QString& name) const
{
const auto entries = d->findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (entry->isPrimitive()) {
- auto *pe = static_cast<PrimitiveTypeEntry *>(entry);
+ auto pe = std::static_pointer_cast<PrimitiveTypeEntry>(entry);
if (pe->preferredTargetLangType())
return pe;
}
@@ -1072,22 +1261,22 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const
return nullptr;
}
-ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const
+ComplexTypeEntryPtr TypeDatabase::findComplexType(const QString& name) const
{
const auto entries = d->findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (entry->isComplex() && useType(entry))
- return static_cast<ComplexTypeEntry*>(entry);
+ return std::static_pointer_cast<ComplexTypeEntry>(entry);
}
return nullptr;
}
-ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const
+ObjectTypeEntryPtr TypeDatabase::findObjectType(const QString& name) const
{
const auto entries = d->findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (entry && entry->isObject() && useType(entry))
- return static_cast<ObjectTypeEntry*>(entry);
+ return std::static_pointer_cast<ObjectTypeEntry>(entry);
}
return nullptr;
}
@@ -1096,25 +1285,25 @@ NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) con
{
NamespaceTypeEntryList result;
const auto entries = d->findTypeRange(name);
- for (TypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (entry->isNamespace())
- result.append(static_cast<NamespaceTypeEntry*>(entry));
+ result.append(std::static_pointer_cast<NamespaceTypeEntry>(entry));
}
return result;
}
-NamespaceTypeEntry *TypeDatabase::findNamespaceType(const QString& name,
+NamespaceTypeEntryPtr TypeDatabase::findNamespaceType(const QString& name,
const QString &fileName) const
{
const auto entries = findNamespaceTypes(name);
// Preferably check on matching file name first, if a pattern was given.
if (!fileName.isEmpty()) {
- for (NamespaceTypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (entry->hasPattern() && entry->matchesFile(fileName))
return entry;
}
}
- for (NamespaceTypeEntry *entry : entries) {
+ for (const auto &entry : entries) {
if (!entry->hasPattern())
return entry;
}
@@ -1126,7 +1315,7 @@ bool TypeDatabase::shouldDropTypeEntry(const QString& fullTypeName) const
return d->m_dropTypeEntries.contains(fullTypeName);
}
-void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries)
+void TypeDatabase::setDropTypeEntries(const QStringList &dropTypeEntries)
{
d->m_dropTypeEntries = dropTypeEntries;
d->m_dropTypeEntries.sort();
@@ -1135,7 +1324,7 @@ void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries)
static bool computeTypeIndexes = true;
static int maxTypeIndex;
-static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2)
+static bool typeEntryLessThan(const TypeEntryCPtr &t1, const TypeEntryCPtr &t2)
{
if (t1->revision() < t2->revision())
return true;
@@ -1145,7 +1334,7 @@ static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2)
static void _computeTypeIndexes()
{
- TypeDatabase* tdb = TypeDatabase::instance();
+ auto *tdb = TypeDatabase::instance();
TypeEntryList list;
@@ -1153,7 +1342,7 @@ static void _computeTypeIndexes()
const auto &allEntries = tdb->entries();
list.reserve(allEntries.size());
for (auto tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) {
- TypeEntry *entry = tit.value();
+ const TypeEntryPtr &entry = tit.value();
if (entry->isPrimitive()
|| entry->isContainer()
|| entry->isFunction()
@@ -1172,7 +1361,7 @@ static void _computeTypeIndexes()
std::sort(list.begin(), list.end(), typeEntryLessThan);
maxTypeIndex = 0;
- for (TypeEntry *e : qAsConst(list))
+ for (const TypeEntryPtr &e : std::as_const(list))
e->setSbkIndex(maxTypeIndex++);
computeTypeIndexes = false;
}
@@ -1209,7 +1398,7 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS
if (versionNumber.isNull())
return false;
ApiVersions &versions = *apiVersions();
- for (int i = 0, size = versions.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = versions.size(); i < size; ++i) {
if (versions.at(i).first.pattern() == packagePattern) {
versions[i].second = versionNumber;
return true;
@@ -1218,7 +1407,7 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS
const QRegularExpression packageRegex(packagePattern);
if (!packageRegex.isValid())
return false;
- versions.append(qMakePair(packageRegex, versionNumber));
+ versions.append(std::make_pair(packageRegex, versionNumber));
return true;
}
@@ -1228,7 +1417,7 @@ bool TypeDatabase::checkApiVersion(const QString &package,
const ApiVersions &versions = *apiVersions();
if (versions.isEmpty()) // Nothing specified: use latest.
return true;
- for (int i = 0, size = versions.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = versions.size(); i < size; ++i) {
if (versions.at(i).first.match(package).hasMatch())
return versions.at(i).second >= vr.since
&& versions.at(i).second <= vr.until;
@@ -1242,21 +1431,6 @@ bool TypeDatabase::hasDroppedTypeEntries() const
}
#ifndef QT_NO_DEBUG_STREAM
-
-template <class Container, class Separator>
-static void formatList(QDebug &d, const char *name, const Container &c, Separator sep)
-{
- if (const int size = c.size()) {
- d << ", " << name << '[' << size << "]=(";
- for (int i = 0; i < size; ++i) {
- if (i)
- d << sep;
- d << c.at(i);
- }
- d << ')';
- }
-}
-
void TypeDatabase::formatDebug(QDebug &debug) const
{
d->formatDebug(debug);
@@ -1299,23 +1473,109 @@ void TypeDatabasePrivate::formatDebug(QDebug &d) const
d << ")\n";
}
d <<"\nglobalUserFunctions=" << m_globalUserFunctions << '\n';
- formatList(d, "globalFunctionMods", m_functionMods, '\n');
+ formatList(d, "globalFunctionMods", m_functionMods, "\n");
d << ')';
}
-void TypeDatabasePrivate::addBuiltInType(TypeEntry *e)
+// Helpers for dumping out primitive type info
+
+struct formatPrimitiveEntry
+{
+ explicit formatPrimitiveEntry(const PrimitiveTypeEntryCPtr &e) : m_pe(e) {}
+
+ PrimitiveTypeEntryCPtr m_pe;
+};
+
+QDebug operator<<(QDebug debug, const formatPrimitiveEntry &fe)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ const QString &name = fe.m_pe->name();
+ const QString &targetLangName = fe.m_pe->targetLangApiName();
+ debug << '"' << name << '"';
+ if (name != targetLangName)
+ debug << " (\"" << targetLangName << "\")";
+ if (fe.m_pe->isBuiltIn())
+ debug << " [builtin]";
+ if (isExtendedCppPrimitive(fe.m_pe)) {
+ debug << " [";
+ if (!isCppPrimitive(fe.m_pe))
+ debug << "extended ";
+ debug << "C++]";
+ }
+ return debug;
+}
+
+// Sort primitive types for displaying; base type and typedef'ed types
+struct PrimitiveFormatListEntry
+{
+ PrimitiveTypeEntryCPtr baseType;
+ PrimitiveTypeEntryCList typedefs;
+};
+
+static bool operator<(const PrimitiveFormatListEntry &e1, const PrimitiveFormatListEntry &e2)
+{
+ return e1.baseType->name() < e2.baseType->name();
+}
+
+using PrimitiveFormatListEntries = QList<PrimitiveFormatListEntry>;
+
+static qsizetype indexOf(const PrimitiveFormatListEntries &e, const PrimitiveTypeEntryCPtr &needle)
+{
+ for (qsizetype i = 0, size = e.size(); i < size; ++i) {
+ if (e.at(i).baseType == needle)
+ return i;
+ }
+ return -1;
+}
+
+void TypeDatabase::formatBuiltinTypes(QDebug debug) const
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+
+ // Determine base types and their typedef'ed types
+ QList<PrimitiveFormatListEntry> primitiveEntries;
+ for (const auto &e : std::as_const(d->m_entries)) {
+ if (e->isPrimitive()) {
+ auto pe = std::static_pointer_cast<const PrimitiveTypeEntry>(e);
+ auto basic = basicReferencedTypeEntry(pe);
+ if (basic != pe) {
+ const auto idx = indexOf(primitiveEntries, basic);
+ if (idx != -1)
+ primitiveEntries[idx].typedefs.append(pe);
+ else
+ primitiveEntries.append(PrimitiveFormatListEntry{basic, {pe}});
+ } else {
+ primitiveEntries.append(PrimitiveFormatListEntry{pe, {}});
+ }
+ }
+ }
+
+ std::sort(primitiveEntries.begin(), primitiveEntries.end());
+
+ for (const auto &e : std::as_const(primitiveEntries)) {
+ debug << "Primitive: " << formatPrimitiveEntry(e.baseType) << '\n';
+ for (const auto &pe : e.typedefs)
+ debug << " " << formatPrimitiveEntry(pe) << '\n';
+ }
+}
+
+void TypeDatabasePrivate::addBuiltInType(const TypeEntryPtr &e)
{
e->setBuiltIn(true);
addType(e);
}
-PrimitiveTypeEntry *
+PrimitiveTypeEntryPtr
TypeDatabasePrivate::addBuiltInPrimitiveType(const QString &name,
- const TypeSystemTypeEntry *root,
+ const TypeSystemTypeEntryCPtr &root,
const QString &rootPackage,
- CustomTypeEntry *targetLang)
+ const CustomTypeEntryPtr &targetLang)
{
- auto *result = new PrimitiveTypeEntry(name, {}, root);
+ auto result = std::make_shared<PrimitiveTypeEntry>(name, QVersionNumber{}, root);
result->setTargetLangApiType(targetLang);
result->setTargetLangPackage(rootPackage);
addBuiltInType(result);
@@ -1324,37 +1584,37 @@ PrimitiveTypeEntry *
void TypeDatabasePrivate::addBuiltInCppStringPrimitiveType(const QString &name,
const QString &viewName,
- const TypeSystemTypeEntry *root,
+ const TypeSystemTypeEntryCPtr &root,
const QString &rootPackage,
- CustomTypeEntry *targetLang)
+ const CustomTypeEntryPtr &targetLang)
{
- auto *stringType = addBuiltInPrimitiveType(name, root, rootPackage,
- targetLang);
- auto *viewType = addBuiltInPrimitiveType(viewName, root, rootPackage,
- nullptr);
+ auto stringType = addBuiltInPrimitiveType(name, root, rootPackage,
+ targetLang);
+ auto viewType = addBuiltInPrimitiveType(viewName, root, rootPackage,
+ nullptr);
viewType->setViewOn(stringType);
}
void TypeDatabasePrivate::addBuiltInPrimitiveTypes()
{
- auto *root = defaultTypeSystemType();
+ auto root = defaultTypeSystemType();
const QString &rootPackage = root->name();
// C++ primitive types
- auto *pyLongEntry = findType(u"PyLong"_s);
+ auto pyLongEntry = findType(u"PyLong"_s);
Q_ASSERT(pyLongEntry && pyLongEntry->isCustom());
- auto *pyLongCustomEntry = static_cast<CustomTypeEntry *>(pyLongEntry);
- auto *pyBoolEntry = findType(u"PyBool"_s);
+ auto pyLongCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyLongEntry);
+ auto pyBoolEntry = findType(u"PyBool"_s);
Q_ASSERT(pyBoolEntry && pyBoolEntry->isCustom());
- auto *sbkCharEntry = findType(u"SbkChar"_s);
+ auto sbkCharEntry = findType(u"SbkChar"_s);
Q_ASSERT(sbkCharEntry && sbkCharEntry->isCustom());
- auto *sbkCharCustomEntry = static_cast<CustomTypeEntry *>(sbkCharEntry);
+ auto sbkCharCustomEntry = std::static_pointer_cast<CustomTypeEntry>(sbkCharEntry);
- auto *pyBoolCustomEntry = static_cast<CustomTypeEntry *>(pyBoolEntry);
+ auto pyBoolCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyBoolEntry);
for (const auto &t : AbstractMetaType::cppIntegralTypes()) {
if (!m_entries.contains(t)) {
- CustomTypeEntry *targetLangApi = pyLongCustomEntry;
+ CustomTypeEntryPtr targetLangApi = pyLongCustomEntry;
if (t == u"bool")
targetLangApi = pyBoolCustomEntry;
else if (AbstractMetaType::cppCharTypes().contains(t))
@@ -1363,25 +1623,25 @@ void TypeDatabasePrivate::addBuiltInPrimitiveTypes()
}
}
- auto *pyFloatEntry = findType(u"PyFloat"_s);
+ auto pyFloatEntry = findType(u"PyFloat"_s);
Q_ASSERT(pyFloatEntry && pyFloatEntry->isCustom());
- auto *pyFloatCustomEntry = static_cast<CustomTypeEntry *>(pyFloatEntry);
+ auto pyFloatCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyFloatEntry);
for (const auto &t : AbstractMetaType::cppFloatTypes()) {
if (!m_entries.contains(t))
addBuiltInPrimitiveType(t, root, rootPackage, pyFloatCustomEntry);
}
- auto *pyUnicodeEntry = findType(u"PyUnicode"_s);
+ auto pyUnicodeEntry = findType(u"PyUnicode"_s);
Q_ASSERT(pyUnicodeEntry && pyUnicodeEntry->isCustom());
- auto *pyUnicodeCustomEntry = static_cast<CustomTypeEntry *>(pyUnicodeEntry);
+ auto pyUnicodeCustomEntry = std::static_pointer_cast<CustomTypeEntry>(pyUnicodeEntry);
- const QString stdString = u"std::string"_s;
+ constexpr auto stdString = "std::string"_L1;
if (!m_entries.contains(stdString)) {
addBuiltInCppStringPrimitiveType(stdString, u"std::string_view"_s,
root, rootPackage,
pyUnicodeCustomEntry);
}
- const QString stdWString = u"std::wstring"_s;
+ constexpr auto stdWString = "std::wstring"_L1;
if (!m_entries.contains(stdWString)) {
addBuiltInCppStringPrimitiveType(stdWString, u"std::wstring_view"_s,
root, rootPackage,
diff --git a/sources/shiboken6/ApiExtractor/typedatabase.h b/sources/shiboken6/ApiExtractor/typedatabase.h
index 0ea7097be..d5adca324 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase.h
+++ b/sources/shiboken6/ApiExtractor/typedatabase.h
@@ -5,26 +5,19 @@
#define TYPEDATABASE_H
#include "include.h"
+#include "modifications_typedefs.h"
#include "typedatabase_typedefs.h"
-#include "typesystem_enums.h"
-#include "typesystem_typedefs.h"
#include <QtCore/QRegularExpression>
#include <QtCore/QStringList>
#include <QtCore/QVersionNumber>
-#include <QtCore/QSharedPointer>
-QT_FORWARD_DECLARE_CLASS(QIODevice)
+#include <memory>
-class ComplexTypeEntry;
-class ContainerTypeEntry;
-class FlagsTypeEntry;
-class FunctionTypeEntry;
-class NamespaceTypeEntry;
-class ObjectTypeEntry;
-class TemplateEntry;
-class TypeEntry;
+QT_FORWARD_DECLARE_CLASS(QIODevice)
+struct OptionDescription;
+class OptionsParser;
struct TypeDatabasePrivate;
struct TypeDatabaseParserContext;
@@ -32,10 +25,6 @@ QT_FORWARD_DECLARE_CLASS(QDebug)
int getMaxTypeIndex();
-class ContainerTypeEntry;
-class PrimitiveTypeEntry;
-class TypeSystemTypeEntry;
-
struct VersionRange
{
bool isNull() const
@@ -62,7 +51,9 @@ struct TypeRejection
QRegularExpression className;
QRegularExpression pattern;
- MatchType matchType;
+ MatchType matchType = ExcludeClass;
+ bool generate; // Current type system
+ mutable bool matched = false;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -72,10 +63,14 @@ QDebug operator<<(QDebug d, const TypeRejection &r);
class TypeDatabase
{
TypeDatabase();
- Q_DISABLE_COPY(TypeDatabase)
public:
+ Q_DISABLE_COPY_MOVE(TypeDatabase)
+
~TypeDatabase();
+ static QList<OptionDescription> options();
+ std::shared_ptr<OptionsParser> createOptionsParser();
+
/**
* Return the type system instance.
* \param newInstance This parameter is useful just for unit testing, because singletons causes
@@ -90,39 +85,37 @@ public:
void addRequiredTargetImport(const QString &moduleName);
- void addTypesystemPath(const QString &typesystem_paths);
-
- void setTypesystemKeywords(const QStringList &keywords);
QStringList typesystemKeywords() const;
IncludeList extraIncludes(const QString &className) const;
- const QStringList &systemIncludes() const;
- void addSystemInclude(const QString &name);
+ const QStringList &forceProcessSystemIncludes() const;
+ void addForceProcessSystemInclude(const QString &name);
- void addInlineNamespaceLookups(const NamespaceTypeEntry *n);
+ void addInlineNamespaceLookups(const NamespaceTypeEntryCPtr &n);
- PrimitiveTypeEntry *findPrimitiveType(const QString &name) const;
- ComplexTypeEntry *findComplexType(const QString &name) const;
- ObjectTypeEntry *findObjectType(const QString &name) const;
+ PrimitiveTypeEntryPtr findPrimitiveType(const QString &name) const;
+ ComplexTypeEntryPtr findComplexType(const QString &name) const;
+ ObjectTypeEntryPtr findObjectType(const QString &name) const;
NamespaceTypeEntryList findNamespaceTypes(const QString &name) const;
- NamespaceTypeEntry *findNamespaceType(const QString &name, const QString &fileName = QString()) const;
- ContainerTypeEntry *findContainerType(const QString &name) const;
- FunctionTypeEntry *findFunctionType(const QString &name) const;
- const TypeSystemTypeEntry *findTypeSystemType(const QString &name) const;
- const TypeSystemTypeEntry *defaultTypeSystemType() const;
+ NamespaceTypeEntryPtr findNamespaceType(const QString &name, const QString &fileName = QString()) const;
+ ContainerTypeEntryPtr findContainerType(const QString &name) const;
+ FunctionTypeEntryPtr findFunctionType(const QString &name) const;
+ TypeSystemTypeEntryCPtr findTypeSystemType(const QString &name) const;
+ TypeSystemTypeEntryCPtr defaultTypeSystemType() const;
+ QString loadedTypeSystemNames() const;
QString defaultPackageName() const;
- TypeEntry *findType(const QString &name) const;
- TypeEntries findTypes(const QString &name) const;
- TypeEntries findCppTypes(const QString &name) const;
+ TypeEntryPtr findType(const QString &name) const;
+ TypeEntryCList findTypes(const QString &name) const;
+ TypeEntryCList findCppTypes(const QString &name) const;
const TypeEntryMultiMap &entries() const;
const TypedefEntryMap &typedefEntries() const;
- PrimitiveTypeEntryList primitiveTypes() const;
+ PrimitiveTypeEntryCList primitiveTypes() const;
- ContainerTypeEntryList containerTypes() const;
+ ContainerTypeEntryCList containerTypes() const;
SmartPointerTypeEntryList smartPointerTypes() const;
@@ -139,21 +132,21 @@ public:
bool isReturnTypeRejected(const QString &className, const QString &typeName,
QString *reason = nullptr) const;
- bool addType(TypeEntry *e, QString *errorMessage = nullptr);
- ConstantValueTypeEntry *addConstantValueTypeEntry(const QString &value,
- const TypeEntry *parent);
- void addTypeSystemType(const TypeSystemTypeEntry *e);
+ bool addType(const TypeEntryPtr &e, QString *errorMessage = nullptr);
+ ConstantValueTypeEntryPtr addConstantValueTypeEntry(const QString &value,
+ const TypeEntryCPtr &parent);
+ void addTypeSystemType(const TypeSystemTypeEntryCPtr &e);
- static ComplexTypeEntry *
- initializeTypeDefEntry(TypedefEntry *typedefEntry,
- const ComplexTypeEntry *source);
+ static ComplexTypeEntryPtr
+ initializeTypeDefEntry(const TypedefEntryPtr &typedefEntry,
+ const ComplexTypeEntryCPtr &source);
- FlagsTypeEntry *findFlagsType(const QString &name) const;
- void addFlagsType(FlagsTypeEntry *fte);
+ FlagsTypeEntryPtr findFlagsType(const QString &name) const;
+ void addFlagsType(const FlagsTypeEntryPtr &fte);
- TemplateEntry *findTemplate(const QString &name) const;
+ TemplateEntryPtr findTemplate(const QString &name) const;
- void addTemplate(TemplateEntry *t);
+ void addTemplate(const TemplateEntryPtr &t);
void addTemplate(const QString &name, const QString &code);
AddedFunctionList globalUserFunctions() const;
@@ -164,24 +157,23 @@ public:
void addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications);
- FunctionModificationList functionModifications(const QString &signature) const;
+ FunctionModificationList
+ globalFunctionModifications(const QStringList &signatures) const;
- void setSuppressWarnings(bool on);
-
- bool addSuppressedWarning(const QString &warning, QString *errorMessage);
+ bool addSuppressedWarning(const QString &warning, bool generate, QString *errorMessage);
bool isSuppressedWarning(QStringView s) const;
- static QString globalNamespaceClassName(const TypeEntry *te);
+ static QString globalNamespaceClassName(const TypeEntryCPtr &te);
// Top level file parsing
bool parseFile(const QString &filename, bool generate = true);
- bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context,
+ bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context,
const QString &filename, const QString &currentPath, bool generate);
// Top level QIODevice parsing for tests.
bool parseFile(QIODevice *device, bool generate = true);
- bool parseFile(const QSharedPointer<TypeDatabaseParserContext> &context,
+ bool parseFile(const std::shared_ptr<TypeDatabaseParserContext> &context,
QIODevice *device, bool generate = true);
static bool setApiVersion(const QString &package, const QString &version);
@@ -193,19 +185,23 @@ public:
bool shouldDropTypeEntry(const QString &fullTypeName) const;
- void setDropTypeEntries(QStringList dropTypeEntries);
+ void setDropTypeEntries(const QStringList &dropTypeEntries);
QString modifiedTypesystemFilepath(const QString &tsFile, const QString &currentPath = QString()) const;
+ void logUnmatched() const;
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const;
#endif
+ void formatBuiltinTypes(QDebug debug) const;
private:
TypeDatabasePrivate *d;
};
#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const TypeEntryCPtr &te);
QDebug operator<<(QDebug d, const TypeEntry *te);
QDebug operator<<(QDebug d, const TypeDatabase &db);
#endif
diff --git a/sources/shiboken6/ApiExtractor/typedatabase_p.h b/sources/shiboken6/ApiExtractor/typedatabase_p.h
index 4d16040cf..fc56c7961 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase_p.h
+++ b/sources/shiboken6/ApiExtractor/typedatabase_p.h
@@ -4,18 +4,22 @@
#ifndef TYPEDATABASE_P_H
#define TYPEDATABASE_P_H
+#include "typesystem_typedefs.h"
+#include "containertypeentry.h"
+
#include <QtCore/QHash>
#include <QtCore/QString>
class TypeDatabase;
-class SmartPointerTypeEntry;
struct TypeDatabaseParserContext
{
- using SmartPointerInstantiations = QHash<SmartPointerTypeEntry *, QString>;
+ using SmartPointerInstantiations = QHash<SmartPointerTypeEntryPtr, QString>;
+ using OpaqueContainerHash = QHash<QString, OpaqueContainers>;
TypeDatabase *db;
SmartPointerInstantiations smartPointerInstantiations;
+ OpaqueContainerHash opaqueContainerHash;
};
#endif // TYPEDATABASE_P_H
diff --git a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h
index bc964eee2..f00c61570 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h
+++ b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h
@@ -4,21 +4,13 @@
#ifndef TYPEDATABASE_TYPEDEFS_H
#define TYPEDATABASE_TYPEDEFS_H
+#include "typesystem_typedefs.h"
+
#include <QtCore/QMultiMap>
#include <QtCore/QString>
#include <QtCore/QList>
-class ConstantValueTypeEntry;
-class ContainerTypeEntry;
-class NamespaceTypeEntry;
-class PrimitiveTypeEntry;
-class SmartPointerTypeEntry;
-class TemplateEntry;
-class TypeEntry;
-class TypedefEntry;
-
-using TypeEntryList = QList<TypeEntry *>;
-using TemplateEntryMap =QMap<QString, TemplateEntry *>;
+using TemplateEntryMap =QMap<QString, TemplateEntryPtr>;
template <class Key, class Value>
struct QMultiMapConstIteratorRange // A range of iterator for a range-based for loop
@@ -32,15 +24,10 @@ struct QMultiMapConstIteratorRange // A range of iterator for a range-based for
ConstIterator m_end;
};
-using TypeEntryMultiMap = QMultiMap<QString, TypeEntry *>;
-using TypeEntryMultiMapConstIteratorRange = QMultiMapConstIteratorRange<QString, TypeEntry *>;
-
-using TypeEntryMap = QMap<QString, TypeEntry *>;
-using TypedefEntryMap = QMap<QString, TypedefEntry *>;
+using TypeEntryMultiMap = QMultiMap<QString, TypeEntryPtr>;
+using TypeEntryMultiMapConstIteratorRange = QMultiMapConstIteratorRange<QString, TypeEntryPtr>;
-using ContainerTypeEntryList = QList<const ContainerTypeEntry *>;
-using NamespaceTypeEntryList = QList<NamespaceTypeEntry *>;
-using PrimitiveTypeEntryList = QList<const PrimitiveTypeEntry *>;
-using SmartPointerTypeEntryList = QList<const SmartPointerTypeEntry *>;
+using TypeEntryMap = QMap<QString, TypeEntryPtr>;
+using TypedefEntryMap = QMap<QString, TypedefEntryPtr>;
#endif // TYPEDATABASE_TYPEDEFS_H
diff --git a/sources/shiboken6/ApiExtractor/typedefentry.h b/sources/shiboken6/ApiExtractor/typedefentry.h
index e0eaf5efc..44646972c 100644
--- a/sources/shiboken6/ApiExtractor/typedefentry.h
+++ b/sources/shiboken6/ApiExtractor/typedefentry.h
@@ -14,18 +14,18 @@ public:
explicit TypedefEntry(const QString &entryName,
const QString &sourceType,
const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
QString sourceType() const;
void setSourceType(const QString &s);
TypeEntry *clone() const override;
- const ComplexTypeEntry *source() const;
- void setSource(const ComplexTypeEntry *source);
+ ComplexTypeEntryCPtr source() const;
+ void setSource(const ComplexTypeEntryCPtr &source);
- ComplexTypeEntry *target() const;
- void setTarget(ComplexTypeEntry *target);
+ ComplexTypeEntryPtr target() const;
+ void setTarget(ComplexTypeEntryPtr target);
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
diff --git a/sources/shiboken6/ApiExtractor/typeparser.cpp b/sources/shiboken6/ApiExtractor/typeparser.cpp
index cff10eb67..11d7bf641 100644
--- a/sources/shiboken6/ApiExtractor/typeparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typeparser.cpp
@@ -8,6 +8,8 @@
#include <QtCore/QStack>
#include <QtCore/QTextStream>
+using namespace Qt::StringLiterals;
+
class Scanner
{
public:
@@ -35,7 +37,7 @@ public:
{
}
- Token nextToken(QString *errorMessage = Q_NULLPTR);
+ Token nextToken(QString *errorMessage = nullptr);
QString identifier() const;
QString msgParseError(const QString &why) const;
@@ -145,8 +147,8 @@ Scanner::Token Scanner::nextToken(QString *errorMessage)
QString Scanner::msgParseError(const QString &why) const
{
- return QStringLiteral("TypeParser: Unable to parse \"")
- + QString(m_chars, m_length) + QStringLiteral("\": ") + why;
+ return "TypeParser: Unable to parse \""_L1
+ + QString(m_chars, m_length) + "\": "_L1 + why;
}
TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
@@ -164,7 +166,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
Scanner::Token tok = scanner.nextToken(errorMessage);
while (tok != Scanner::NoToken) {
if (tok == Scanner::InvalidToken)
- return TypeInfo();
+ return {};
// switch (tok) {
// case Scanner::StarToken: printf(" - *\n"); break;
@@ -197,12 +199,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
stack.top().setReferenceType(RValueReference);
break;
case RValueReference:
- const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers"));
+ const QString message = scanner.msgParseError("Too many '&' qualifiers"_L1);
if (errorMessage)
*errorMessage = message;
else
qWarning().noquote().nospace() << message;
- return TypeInfo();
+ return {};
}
break;
case Scanner::LessThanToken:
@@ -244,12 +246,12 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
case Scanner::OpenParenToken: // function pointers not supported
case Scanner::CloseParenToken: {
- const QString message = scanner.msgParseError(QStringLiteral("Function pointers are not supported"));
+ const QString message = scanner.msgParseError("Function pointers are not supported"_L1);
if (errorMessage)
*errorMessage = message;
else
qWarning().noquote().nospace() << message;
- return TypeInfo();
+ return {};
}
case Scanner::Identifier:
@@ -279,11 +281,11 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
break;
}
- tok = scanner.nextToken();
+ tok = scanner.nextToken(errorMessage);
}
if (stack.isEmpty() || stack.constFirst().qualifiedName().isEmpty()) {
- *errorMessage = u"Unable to parse type \""_qs + str + u"\"."_qs;
+ *errorMessage = u"Unable to parse type \""_s + str + u"\"."_s;
return {};
}
return stack.constFirst();
diff --git a/sources/shiboken6/ApiExtractor/typeparser.h b/sources/shiboken6/ApiExtractor/typeparser.h
index 8e81435b2..97634b5db 100644
--- a/sources/shiboken6/ApiExtractor/typeparser.h
+++ b/sources/shiboken6/ApiExtractor/typeparser.h
@@ -4,8 +4,6 @@
#ifndef TYPEPARSER_H
#define TYPEPARSER_H
-#include "parser/codemodel_enums.h"
-
#include <QtCore/QString>
class TypeInfo;
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index f0a4a9027..99d42b668 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -5,14 +5,16 @@
#include "arraytypeentry.h"
#include "codesnip.h"
#include "complextypeentry.h"
+#include "configurabletypeentry.h"
#include "constantvaluetypeentry.h"
#include "containertypeentry.h"
-#include "customconversion.h"
#include "customtypenentry.h"
+#include "debughelpers_p.h"
#include "enumtypeentry.h"
#include "enumvaluetypeentry.h"
#include "flagstypeentry.h"
#include "functiontypeentry.h"
+#include "include.h"
#include "namespacetypeentry.h"
#include "objecttypeentry.h"
#include "primitivetypeentry.h"
@@ -27,7 +29,6 @@
#include "abstractmetatype.h"
#include "typedatabase.h"
#include "modifications.h"
-#include "messages.h"
#include "sourcelocation.h"
#include "qtcompat.h"
@@ -39,7 +40,7 @@
using namespace Qt::StringLiterals;
-static QString buildName(const QString &entryName, const TypeEntry *parent)
+static QString buildName(const QString &entryName, const TypeEntryCPtr &parent)
{
return parent == nullptr || parent->type() == TypeEntry::TypeSystemType
? entryName : parent->name() + u"::"_s + entryName;
@@ -51,31 +52,31 @@ static QString buildName(const QString &entryName, const TypeEntry *parent)
class TypeEntryPrivate
{
public:
+ TypeEntryPrivate(const TypeEntryPrivate &) = default; // Enable copy for cloning.
+ TypeEntryPrivate &operator=(const TypeEntryPrivate &) = delete;
+ TypeEntryPrivate(TypeEntryPrivate &&) = delete;
+ TypeEntryPrivate &operator=(TypeEntryPrivate &&) = delete;
+
explicit TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr,
- const TypeEntry *parent);
- virtual ~TypeEntryPrivate();
+ const TypeEntryCPtr &parent);
+ virtual ~TypeEntryPrivate() = default;
QString shortName() const;
- const TypeEntry *m_parent;
+ TypeEntryCPtr m_parent;
QString m_name; // C++ fully qualified
mutable QString m_cachedShortName; // C++ excluding inline namespaces
QString m_entryName;
QString m_targetLangPackage;
mutable QString m_cachedTargetLangName; // "Foo.Bar"
mutable QString m_cachedTargetLangEntryName; // "Bar"
- CodeSnipList m_codeSnips;
- DocModificationList m_docModifications;
IncludeList m_extraIncludes;
- IncludeList m_argumentIncludes;
Include m_include;
- QString m_targetConversionRule;
QVersionNumber m_version;
- CustomConversion *m_customConversion = nullptr;
SourceLocation m_sourceLocation; // XML file
TypeEntry::CodeGeneration m_codeGeneration = TypeEntry::GenerateCode;
- TypeEntry *m_viewOn = nullptr;
- CustomTypeEntry *m_targetLangApiType = nullptr;
+ TypeEntryPtr m_viewOn;
+ CustomTypeEntryPtr m_targetLangApiType;
int m_revision = 0;
int m_sbkIndex = 0;
TypeEntry::Type m_type;
@@ -85,7 +86,7 @@ public:
};
TypeEntryPrivate::TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
m_parent(parent),
m_name(buildName(entryName, parent)),
m_entryName(entryName),
@@ -94,13 +95,8 @@ TypeEntryPrivate::TypeEntryPrivate(const QString &entryName, TypeEntry::Type t,
{
}
-TypeEntryPrivate::~TypeEntryPrivate()
-{
- delete m_customConversion;
-}
-
TypeEntry::TypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new TypeEntryPrivate(entryName, t, vr, parent))
{
}
@@ -111,36 +107,6 @@ TypeEntry::TypeEntry(TypeEntryPrivate *d) : m_d(d)
TypeEntry::~TypeEntry() = default;
-const CodeSnipList &TypeEntry::codeSnips() const
-{
- return m_d->m_codeSnips;
-}
-
-CodeSnipList &TypeEntry::codeSnips()
-{
- return m_d->m_codeSnips;
-}
-
-void TypeEntry::setCodeSnips(const CodeSnipList &codeSnips)
-{
- m_d->m_codeSnips = codeSnips;
-}
-
-void TypeEntry::addCodeSnip(const CodeSnip &codeSnip)
-{
- m_d->m_codeSnips << codeSnip;
-}
-
-void TypeEntry::setDocModification(const DocModificationList &docMods)
-{
- m_d->m_docModifications << docMods;
-}
-
-DocModificationList TypeEntry::docModifications() const
-{
- return m_d->m_docModifications;
-}
-
const IncludeList &TypeEntry::extraIncludes() const
{
return m_d->m_extraIncludes;
@@ -157,17 +123,6 @@ void TypeEntry::addExtraInclude(const Include &newInclude)
m_d->m_extraIncludes.append(newInclude);
}
-const IncludeList &TypeEntry::argumentIncludes() const
-{
- return m_d->m_argumentIncludes;
-}
-
-void TypeEntry::addArgumentInclude(const Include &newInclude)
-{
- if (!m_d->m_argumentIncludes.contains(newInclude))
- m_d->m_argumentIncludes.append(newInclude);
-}
-
Include TypeEntry::include() const
{
return m_d->m_include;
@@ -187,36 +142,20 @@ void TypeEntry::setInclude(const Include &inc)
}
}
-void TypeEntry::setTargetConversionRule(const QString &conversionRule)
-{
- m_d->m_targetConversionRule = conversionRule;
-}
-
-QString TypeEntry::targetConversionRule() const
-{
- return m_d->m_targetConversionRule;
-}
-
QVersionNumber TypeEntry::version() const
{
return m_d->m_version;
}
-bool TypeEntry::hasTargetConversionRule() const
+bool isCppPrimitive(const TypeEntryCPtr &e)
{
- return !m_d->m_targetConversionRule.isEmpty();
-}
-
-bool TypeEntry::isCppPrimitive() const
-{
- if (!isPrimitive())
+ if (!e->isPrimitive())
return false;
- if (m_d->m_type == VoidType)
+ if (e->type() == TypeEntry::VoidType)
return true;
- const PrimitiveTypeEntry *referencedType =
- static_cast<const PrimitiveTypeEntry *>(this)->basicReferencedTypeEntry();
+ PrimitiveTypeEntryCPtr referencedType = basicReferencedTypeEntry(e);
const QString &typeName = referencedType->name();
return AbstractMetaType::cppPrimitiveTypes().contains(typeName);
}
@@ -226,17 +165,17 @@ TypeEntry::Type TypeEntry::type() const
return m_d->m_type;
}
-const TypeEntry *TypeEntry::parent() const
+TypeEntryCPtr TypeEntry::parent() const
{
return m_d->m_parent;
}
-void TypeEntry::setParent(const TypeEntry *p)
+void TypeEntry::setParent(const TypeEntryCPtr &p)
{
m_d->m_parent = p;
}
-bool TypeEntry::isChildOf(const TypeEntry *p) const
+bool TypeEntry::isChildOf(const TypeEntryCPtr &p) const
{
for (auto e = m_d->m_parent; e; e = e->parent()) {
if (e == p)
@@ -245,18 +184,18 @@ bool TypeEntry::isChildOf(const TypeEntry *p) const
return false;
}
-const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const
+TypeSystemTypeEntryCPtr typeSystemTypeEntry(TypeEntryCPtr e)
{
- for (auto e = this; e; e = e->parent()) {
+ for (; e; e = e->parent()) {
if (e->type() == TypeEntry::TypeSystemType)
- return static_cast<const TypeSystemTypeEntry *>(e);
+ return std::static_pointer_cast<const TypeSystemTypeEntry>(e);
}
- return nullptr;
+ return {};
}
-const TypeEntry *TypeEntry::targetLangEnclosingEntry() const
+TypeEntryCPtr targetLangEnclosingEntry(const TypeEntryCPtr &e)
{
- auto result = m_d->m_parent;
+ auto result = e->parent();
while (result && result->type() != TypeEntry::TypeSystemType
&& !NamespaceTypeEntry::isVisibleScope(result)) {
result = result->parent();
@@ -387,11 +326,11 @@ QString TypeEntry::name() const
QString TypeEntryPrivate::shortName() const
{
if (m_cachedShortName.isEmpty()) {
- QVarLengthArray<const TypeEntry *> parents;
+ QVarLengthArray<TypeEntryCPtr > parents;
bool foundInlineNamespace = false;
for (auto p = m_parent; p != nullptr && p->type() != TypeEntry::TypeSystemType; p = p->parent()) {
if (p->type() == TypeEntry::NamespaceType
- && static_cast<const NamespaceTypeEntry *>(p)->isInlineNamespace()) {
+ && std::static_pointer_cast<const NamespaceTypeEntry>(p)->isInlineNamespace()) {
foundInlineNamespace = true;
} else {
parents.append(p);
@@ -399,7 +338,7 @@ QString TypeEntryPrivate::shortName() const
}
if (foundInlineNamespace) {
m_cachedShortName.reserve(m_name.size());
- for (int i = parents.size() - 1; i >= 0; --i) {
+ for (auto i = parents.size() - 1; i >= 0; --i) {
m_cachedShortName.append(parents.at(i)->entryName());
m_cachedShortName.append(u"::"_s);
}
@@ -456,7 +395,7 @@ QString TypeEntry::qualifiedCppName() const
return m_d->m_name;
}
-const CustomTypeEntry *TypeEntry::targetLangApiType() const
+CustomTypeEntryCPtr TypeEntry::targetLangApiType() const
{
return m_d->m_targetLangApiType;
}
@@ -466,7 +405,7 @@ bool TypeEntry::hasTargetLangApiType() const
return m_d->m_targetLangApiType != nullptr;
}
-void TypeEntry::setTargetLangApiType(CustomTypeEntry *cte)
+void TypeEntry::setTargetLangApiType(const CustomTypeEntryPtr &cte)
{
m_d->m_targetLangApiType = cte;
}
@@ -526,18 +465,12 @@ void TypeEntry::setSourceLocation(const SourceLocation &sourceLocation)
m_d->m_sourceLocation = sourceLocation;
}
-const PrimitiveTypeEntry *TypeEntry::asPrimitive() const
+bool isUserPrimitive(const TypeEntryCPtr &e)
{
- Q_ASSERT(m_d->m_type == PrimitiveType);
- return static_cast<const PrimitiveTypeEntry *>(this);
-}
-
-bool TypeEntry::isUserPrimitive() const
-{
- if (!isPrimitive())
+ if (!e->isPrimitive())
return false;
- const auto *type = asPrimitive()->basicReferencedTypeEntry();
- return !type->isCppPrimitive()
+ const auto type = basicReferencedTypeEntry(e);
+ return !isCppPrimitive(type)
&& type->qualifiedCppName() != u"std::string";
}
@@ -546,21 +479,21 @@ bool TypeEntry::isWrapperType() const
return isObject() || isValue() || isSmartPointer();
}
-bool TypeEntry::isCppIntegralPrimitive() const
+bool isCppIntegralPrimitive(const TypeEntryCPtr &e)
{
- if (!isCppPrimitive())
+ if (!isCppPrimitive(e))
return false;
- const auto *type = asPrimitive()->basicReferencedTypeEntry();
+ const auto type = basicReferencedTypeEntry(e);
return AbstractMetaType::cppIntegralTypes().contains(type->qualifiedCppName());
}
-bool TypeEntry::isExtendedCppPrimitive() const
+bool isExtendedCppPrimitive(const TypeEntryCPtr &e)
{
- if (isCppPrimitive())
+ if (isCppPrimitive(e))
return true;
- if (!isPrimitive())
+ if (!e->isPrimitive())
return false;
- const auto *type = asPrimitive()->basicReferencedTypeEntry();
+ const auto type = basicReferencedTypeEntry(e);
const QString &name = type->qualifiedCppName();
return name == u"std::string" || name == u"std::wstring";
}
@@ -611,27 +544,12 @@ bool TypeEntry::isComplex() const
return false;
}
-bool TypeEntry::hasCustomConversion() const
-{
- return m_d->m_customConversion != nullptr;
-}
-
-void TypeEntry::setCustomConversion(CustomConversion* customConversion)
-{
- m_d->m_customConversion = customConversion;
-}
-
-CustomConversion* TypeEntry::customConversion() const
-{
- return m_d->m_customConversion;
-}
-
-TypeEntry *TypeEntry::viewOn() const
+TypeEntryPtr TypeEntry::viewOn() const
{
return m_d->m_viewOn;
}
-void TypeEntry::setViewOn(TypeEntry *v)
+void TypeEntry::setViewOn(const TypeEntryPtr &v)
{
m_d->m_viewOn = v;
}
@@ -642,10 +560,10 @@ TypeEntry *TypeEntry::clone() const
}
// Take over parameters relevant for typedefs
-void TypeEntry::useAsTypedef(const TypeEntry *source)
+void TypeEntry::useAsTypedef(const TypeEntryCPtr &source)
{
// XML Typedefs are in the global namespace for now.
- m_d->m_parent = source->typeSystemTypeEntry();
+ m_d->m_parent = typeSystemTypeEntry(source);
m_d->m_entryName = source->m_d->m_entryName;
m_d->m_name = source->m_d->m_name;
m_d->m_targetLangPackage = source->m_d->m_targetLangPackage;
@@ -665,7 +583,7 @@ public:
};
CustomTypeEntry::CustomTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new CustomTypeEntryPrivate(entryName, CustomType, vr, parent))
{
}
@@ -746,11 +664,15 @@ class TypeSystemTypeEntryPrivate : public TypeEntryPrivate
public:
using TypeEntryPrivate::TypeEntryPrivate;
+ CodeSnipList m_codeSnips;
TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Disabled;
+ QString m_subModuleOf;
+ QString m_namespaceBegin;
+ QString m_namespaceEnd;
};
TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new TypeSystemTypeEntryPrivate(entryName, TypeSystemType, vr, parent))
{
}
@@ -766,6 +688,60 @@ TypeEntry *TypeSystemTypeEntry::clone() const
return new TypeSystemTypeEntry(new TypeSystemTypeEntryPrivate(*d));
}
+const CodeSnipList &TypeSystemTypeEntry::codeSnips() const
+{
+ S_D(const TypeSystemTypeEntry);
+ return d->m_codeSnips;
+}
+
+CodeSnipList &TypeSystemTypeEntry::codeSnips()
+{
+ S_D(TypeSystemTypeEntry);
+ return d->m_codeSnips;
+}
+
+void TypeSystemTypeEntry::addCodeSnip(const CodeSnip &codeSnip)
+{
+ S_D(TypeSystemTypeEntry);
+ d->m_codeSnips.append(codeSnip);
+}
+
+QString TypeSystemTypeEntry::subModuleOf() const
+{
+ S_D(const TypeSystemTypeEntry);
+ return d->m_subModuleOf;
+}
+
+void TypeSystemTypeEntry::setSubModule(const QString &s)
+{
+ S_D(TypeSystemTypeEntry);
+ d->m_subModuleOf = s;
+}
+
+const QString &TypeSystemTypeEntry::namespaceBegin() const
+{
+ S_D(const TypeSystemTypeEntry);
+ return d->m_namespaceBegin;
+}
+
+void TypeSystemTypeEntry::setNamespaceBegin(const QString &p)
+{
+ S_D(TypeSystemTypeEntry);
+ d->m_namespaceBegin = p;
+}
+
+const QString &TypeSystemTypeEntry::namespaceEnd() const
+{
+ S_D(const TypeSystemTypeEntry);
+ return d->m_namespaceEnd;
+}
+
+void TypeSystemTypeEntry::setNamespaceEnd(const QString &n)
+{
+ S_D(TypeSystemTypeEntry);
+ d->m_namespaceEnd = n;
+}
+
TypeSystem::SnakeCase TypeSystemTypeEntry::snakeCase() const
{
S_D(const TypeSystemTypeEntry);
@@ -820,7 +796,7 @@ public:
};
TemplateArgumentEntry::TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new TemplateArgumentEntryPrivate(entryName, TemplateArgumentType, vr, parent))
{
}
@@ -852,30 +828,30 @@ TemplateArgumentEntry::TemplateArgumentEntry(TemplateArgumentEntryPrivate *d) :
class ArrayTypeEntryPrivate : public TypeEntryPrivate
{
public:
- explicit ArrayTypeEntryPrivate(const TypeEntry *nested_type, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ explicit ArrayTypeEntryPrivate(const TypeEntryCPtr &nested_type, const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
TypeEntryPrivate(u"Array"_s, TypeEntry::ArrayType, vr, parent),
m_nestedType(nested_type)
{
}
- const TypeEntry *m_nestedType;
+ TypeEntryCPtr m_nestedType;
};
-ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ArrayTypeEntry::ArrayTypeEntry(const TypeEntryCPtr &nested_type, const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
TypeEntry(new ArrayTypeEntryPrivate(nested_type, vr, parent))
{
Q_ASSERT(nested_type);
}
-void ArrayTypeEntry::setNestedTypeEntry(TypeEntry *nested)
+void ArrayTypeEntry::setNestedTypeEntry(const TypeEntryPtr &nested)
{
S_D(ArrayTypeEntry);
d->m_nestedType = nested;
}
-const TypeEntry *ArrayTypeEntry::nestedTypeEntry() const
+TypeEntryCPtr ArrayTypeEntry::nestedTypeEntry() const
{
S_D(const ArrayTypeEntry);
return d->m_nestedType;
@@ -903,19 +879,20 @@ class PrimitiveTypeEntryPrivate : public TypeEntryPrivate
{
public:
PrimitiveTypeEntryPrivate(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntryPrivate(entryName, TypeEntry::PrimitiveType, vr, parent),
m_preferredTargetLangType(true)
{
}
QString m_defaultConstructor;
+ CustomConversionPtr m_customConversion;
+ PrimitiveTypeEntryPtr m_referencedTypeEntry;
uint m_preferredTargetLangType : 1;
- PrimitiveTypeEntry* m_referencedTypeEntry = nullptr;
};
PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new PrimitiveTypeEntryPrivate(entryName, vr, parent))
{
}
@@ -938,29 +915,35 @@ bool PrimitiveTypeEntry::hasDefaultConstructor() const
return !d->m_defaultConstructor.isEmpty();
}
-PrimitiveTypeEntry *PrimitiveTypeEntry::referencedTypeEntry() const
+PrimitiveTypeEntryPtr PrimitiveTypeEntry::referencedTypeEntry() const
{
S_D(const PrimitiveTypeEntry);
return d->m_referencedTypeEntry;
}
-void PrimitiveTypeEntry::setReferencedTypeEntry(PrimitiveTypeEntry *referencedTypeEntry)
+void PrimitiveTypeEntry::setReferencedTypeEntry(PrimitiveTypeEntryPtr referencedTypeEntry)
{
S_D(PrimitiveTypeEntry);
d->m_referencedTypeEntry = referencedTypeEntry;
}
-const PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const
+PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const PrimitiveTypeEntryCPtr &e)
{
- auto *result = this;
- while (auto *referenced = result->referencedTypeEntry())
+ auto result = e;
+ while (auto referenced = result->referencedTypeEntry())
result = referenced;
return result;
}
-const PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedNonBuiltinTypeEntry() const
+PrimitiveTypeEntryCPtr basicReferencedTypeEntry(const TypeEntryCPtr &e)
{
- auto *result = this;
+ Q_ASSERT(e->isPrimitive());
+ return basicReferencedTypeEntry(std::static_pointer_cast<const PrimitiveTypeEntry>(e));
+}
+
+PrimitiveTypeEntryCPtr basicReferencedNonBuiltinTypeEntry(const PrimitiveTypeEntryCPtr &e)
+{
+ auto result = e;
for (; result->referencedTypeEntry() ; result = result->referencedTypeEntry()) {
if (!result->isBuiltIn())
break;
@@ -986,6 +969,24 @@ void PrimitiveTypeEntry::setPreferredTargetLangType(bool b)
d->m_preferredTargetLangType = b;
}
+bool PrimitiveTypeEntry::hasCustomConversion() const
+{
+ S_D(const PrimitiveTypeEntry);
+ return bool(d->m_customConversion);
+}
+
+void PrimitiveTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
+{
+ S_D(PrimitiveTypeEntry);
+ d->m_customConversion = customConversion;
+}
+
+CustomConversionPtr PrimitiveTypeEntry::customConversion() const
+{
+ S_D(const PrimitiveTypeEntry);
+ return d->m_customConversion;
+}
+
TypeEntry *PrimitiveTypeEntry::clone() const
{
S_D(const PrimitiveTypeEntry);
@@ -997,24 +998,87 @@ PrimitiveTypeEntry::PrimitiveTypeEntry(PrimitiveTypeEntryPrivate *d)
{
}
-// ----------------- EnumTypeEntry
-class EnumTypeEntryPrivate : public TypeEntryPrivate
+// ----------------- ConfigurableTypeEntry
+
+class ConfigurableTypeEntryPrivate : public TypeEntryPrivate
{
public:
using TypeEntryPrivate::TypeEntryPrivate;
- const EnumValueTypeEntry *m_nullValue = nullptr;
+ QString m_configCondition;
+};
+
+ConfigurableTypeEntry::ConfigurableTypeEntry(const QString &entryName, Type t,
+ const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
+ TypeEntry(new ConfigurableTypeEntryPrivate(entryName, t, vr, parent))
+{
+}
+
+ConfigurableTypeEntry::ConfigurableTypeEntry(ConfigurableTypeEntryPrivate *d) :
+ TypeEntry(d)
+{
+}
+
+TypeEntry *ConfigurableTypeEntry::clone() const
+{
+ S_D(const ConfigurableTypeEntry);
+ return new ConfigurableTypeEntry(new ConfigurableTypeEntryPrivate(*d));
+}
+
+QString ConfigurableTypeEntry::configCondition() const
+{
+ S_D(const ConfigurableTypeEntry);
+ return d->m_configCondition;
+}
+
+void ConfigurableTypeEntry::setConfigCondition(const QString &c)
+{
+ S_D(ConfigurableTypeEntry);
+ d->m_configCondition = c;
+ if (!d->m_configCondition.startsWith(u'#'))
+ d->m_configCondition.prepend(u"#if ");
+}
+
+bool ConfigurableTypeEntry::hasConfigCondition() const
+{
+ S_D(const ConfigurableTypeEntry);
+ return !d->m_configCondition.isEmpty();
+}
+
+// ----------------- EnumTypeEntry
+class EnumTypeEntryPrivate : public ConfigurableTypeEntryPrivate
+{
+public:
+ using ConfigurableTypeEntryPrivate::ConfigurableTypeEntryPrivate;
+
+ EnumValueTypeEntryCPtr m_nullValue;
QStringList m_rejectedEnums;
- FlagsTypeEntry *m_flags = nullptr;
+ FlagsTypeEntryPtr m_flags;
+ QString m_cppType;
+ QString m_docFile;
+ TypeSystem::PythonEnumType m_pythonEnumType = TypeSystem::PythonEnumType::Unspecified;
};
EnumTypeEntry::EnumTypeEntry(const QString &entryName,
const QVersionNumber &vr,
- const TypeEntry *parent) :
- TypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent))
+ const TypeEntryCPtr &parent) :
+ ConfigurableTypeEntry(new EnumTypeEntryPrivate(entryName, EnumType, vr, parent))
{
}
+TypeSystem::PythonEnumType EnumTypeEntry::pythonEnumType() const
+{
+ S_D(const EnumTypeEntry);
+ return d->m_pythonEnumType;
+}
+
+void EnumTypeEntry::setPythonEnumType(TypeSystem::PythonEnumType t)
+{
+ S_D(EnumTypeEntry);
+ d->m_pythonEnumType = t;
+}
+
QString EnumTypeEntry::targetLangQualifier() const
{
const QString q = qualifier();
@@ -1032,30 +1096,42 @@ QString EnumTypeEntry::qualifier() const
parentEntry->name() : QString();
}
-const EnumValueTypeEntry *EnumTypeEntry::nullValue() const
+EnumValueTypeEntryCPtr EnumTypeEntry::nullValue() const
{
S_D(const EnumTypeEntry);
return d->m_nullValue;
}
-void EnumTypeEntry::setNullValue(const EnumValueTypeEntry *n)
+void EnumTypeEntry::setNullValue(const EnumValueTypeEntryCPtr &n)
{
S_D(EnumTypeEntry);
d->m_nullValue = n;
}
-void EnumTypeEntry::setFlags(FlagsTypeEntry *flags)
+void EnumTypeEntry::setFlags(const FlagsTypeEntryPtr &flags)
{
S_D(EnumTypeEntry);
d->m_flags = flags;
}
-FlagsTypeEntry *EnumTypeEntry::flags() const
+FlagsTypeEntryPtr EnumTypeEntry::flags() const
{
S_D(const EnumTypeEntry);
return d->m_flags;
}
+QString EnumTypeEntry::cppType() const
+{
+ S_D(const EnumTypeEntry);
+ return d->m_cppType;
+}
+
+void EnumTypeEntry::setCppType(const QString &t)
+{
+ S_D(EnumTypeEntry);
+ d->m_cppType = t;
+}
+
bool EnumTypeEntry::isEnumValueRejected(const QString &name) const
{
S_D(const EnumTypeEntry);
@@ -1074,6 +1150,18 @@ QStringList EnumTypeEntry::enumValueRejections() const
return d->m_rejectedEnums;
}
+QString EnumTypeEntry::docFile() const
+{
+ S_D(const EnumTypeEntry);
+ return d->m_docFile;
+}
+
+void EnumTypeEntry::setDocFile(const QString &df)
+{
+ S_D(EnumTypeEntry);
+ d->m_docFile = df;
+}
+
TypeEntry *EnumTypeEntry::clone() const
{
S_D(const EnumTypeEntry);
@@ -1081,7 +1169,7 @@ TypeEntry *EnumTypeEntry::clone() const
}
EnumTypeEntry::EnumTypeEntry(EnumTypeEntryPrivate *d) :
- TypeEntry(d)
+ ConfigurableTypeEntry(d)
{
}
@@ -1090,7 +1178,7 @@ class EnumValueTypeEntryPrivate : public TypeEntryPrivate
{
public:
EnumValueTypeEntryPrivate(const QString &name, const QString &value,
- const EnumTypeEntry *enclosingEnum,
+ const EnumTypeEntryCPtr &enclosingEnum,
bool isScopedEnum,
const QVersionNumber &vr) :
TypeEntryPrivate(name, TypeEntry::EnumValue, vr,
@@ -1101,11 +1189,11 @@ public:
}
QString m_value;
- const EnumTypeEntry *m_enclosingEnum;
+ EnumTypeEntryCPtr m_enclosingEnum;
};
EnumValueTypeEntry::EnumValueTypeEntry(const QString &name, const QString &value,
- const EnumTypeEntry *enclosingEnum,
+ const EnumTypeEntryCPtr &enclosingEnum,
bool isScopedEnum,
const QVersionNumber &vr) :
TypeEntry(new EnumValueTypeEntryPrivate(name, value, enclosingEnum, isScopedEnum, vr))
@@ -1118,7 +1206,7 @@ QString EnumValueTypeEntry::value() const
return d->m_value;
}
-const EnumTypeEntry *EnumValueTypeEntry::enclosingEnum() const
+EnumTypeEntryCPtr EnumValueTypeEntry::enclosingEnum() const
{
S_D(const EnumValueTypeEntry);
return d->m_enclosingEnum;
@@ -1143,11 +1231,11 @@ public:
QString m_originalName;
QString m_flagsName;
- EnumTypeEntry *m_enum = nullptr;
+ EnumTypeEntryPtr m_enum;
};
FlagsTypeEntry::FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new FlagsTypeEntryPrivate(entryName, FlagsType, vr, parent))
{
}
@@ -1189,13 +1277,13 @@ void FlagsTypeEntry::setFlagsName(const QString &name)
d->m_flagsName = name;
}
-EnumTypeEntry *FlagsTypeEntry::originator() const
+EnumTypeEntryPtr FlagsTypeEntry::originator() const
{
S_D(const FlagsTypeEntry);
return d->m_enum;
}
-void FlagsTypeEntry::setOriginator(EnumTypeEntry *e)
+void FlagsTypeEntry::setOriginator(const EnumTypeEntryPtr &e)
{
S_D(FlagsTypeEntry);
d->m_enum = e;
@@ -1209,7 +1297,7 @@ TypeEntry *FlagsTypeEntry::clone() const
// ----------------- ConstantValueTypeEntry
ConstantValueTypeEntry::ConstantValueTypeEntry(const QString& name,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(name, ConstantValueType, QVersionNumber(0, 0), parent)
{
}
@@ -1220,13 +1308,13 @@ ConstantValueTypeEntry::ConstantValueTypeEntry(TypeEntryPrivate *d) :
}
// ----------------- ComplexTypeEntry
-class ComplexTypeEntryPrivate : public TypeEntryPrivate
+class ComplexTypeEntryPrivate : public ConfigurableTypeEntryPrivate
{
public:
ComplexTypeEntryPrivate(const QString &entryName, TypeEntry::Type t,
const QVersionNumber &vr,
- const TypeEntry *parent) :
- TypeEntryPrivate(entryName, t, vr, parent),
+ const TypeEntryCPtr &parent) :
+ ConfigurableTypeEntryPrivate(entryName, t, vr, parent),
m_qualifiedCppName(buildName(entryName, parent)),
m_polymorphicBase(false),
m_genericClass(false),
@@ -1236,6 +1324,10 @@ public:
AddedFunctionList m_addedFunctions;
FunctionModificationList m_functionMods;
+ CodeSnipList m_codeSnips;
+ DocModificationList m_docModifications;
+ DocModificationList m_functionDocModifications;
+ IncludeList m_argumentIncludes;
QSet<QString> m_generateFunctions;
FieldModificationList m_fieldMods;
QList<TypeSystemProperty> m_properties;
@@ -1255,7 +1347,7 @@ public:
ComplexTypeEntry::CopyableFlag m_copyableFlag = ComplexTypeEntry::Unknown;
QString m_hashFunction;
- const ComplexTypeEntry* m_baseContainerType = nullptr;
+ ComplexTypeEntryCPtr m_baseContainerType;
// For class functions
TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified;
TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified;
@@ -1270,8 +1362,8 @@ public:
ComplexTypeEntry::ComplexTypeEntry(const QString &entryName, TypeEntry::Type t,
const QVersionNumber &vr,
- const TypeEntry *parent) :
- TypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent))
+ const TypeEntryCPtr &parent) :
+ ConfigurableTypeEntry(new ComplexTypeEntryPrivate(entryName, t, vr, parent))
{
}
@@ -1334,17 +1426,77 @@ void ComplexTypeEntry::addFunctionModification(const FunctionModification &funct
d->m_functionMods << functionModification;
}
-FunctionModificationList ComplexTypeEntry::functionModifications(const QString &signature) const
+FunctionModificationList
+ ComplexTypeEntry::functionModifications(const QStringList &signatures) const
{
S_D(const ComplexTypeEntry);
FunctionModificationList lst;
for (const auto &mod : std::as_const(d->m_functionMods)) {
- if (mod.matches(signature))
+ if (mod.matches(signatures))
lst << mod;
}
return lst;
}
+const CodeSnipList &ComplexTypeEntry::codeSnips() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_codeSnips;
+}
+
+CodeSnipList &ComplexTypeEntry::codeSnips()
+{
+ S_D(ComplexTypeEntry);
+ return d->m_codeSnips;
+}
+
+void ComplexTypeEntry::setCodeSnips(const CodeSnipList &codeSnips)
+{
+ S_D(ComplexTypeEntry);
+ d->m_codeSnips = codeSnips;
+}
+
+void ComplexTypeEntry::addCodeSnip(const CodeSnip &codeSnip)
+{
+ S_D(ComplexTypeEntry);
+ d->m_codeSnips << codeSnip;
+}
+
+void ComplexTypeEntry::setDocModification(const DocModificationList &docMods)
+{
+ S_D(ComplexTypeEntry);
+ for (const auto &m : docMods) {
+ if (m.signature().isEmpty())
+ d->m_docModifications << m;
+ else
+ d->m_functionDocModifications << m;
+ }
+}
+
+DocModificationList ComplexTypeEntry::docModifications() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_docModifications;
+}
+
+DocModificationList ComplexTypeEntry::functionDocModifications() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_functionDocModifications;
+}
+
+const IncludeList &ComplexTypeEntry::argumentIncludes() const
+{
+ S_D(const ComplexTypeEntry);
+ return d->m_argumentIncludes;
+}
+
+void ComplexTypeEntry::addArgumentInclude(const Include &newInclude)
+{
+ S_D(ComplexTypeEntry);
+ IncludeGroup::appendInclude(newInclude, &d->m_argumentIncludes);
+}
+
AddedFunctionList ComplexTypeEntry::addedFunctions() const
{
S_D(const ComplexTypeEntry);
@@ -1537,13 +1689,13 @@ void ComplexTypeEntry::setHashFunction(const QString &hashFunction)
d->m_hashFunction = hashFunction;
}
-void ComplexTypeEntry::setBaseContainerType(const ComplexTypeEntry *baseContainer)
+void ComplexTypeEntry::setBaseContainerType(const ComplexTypeEntryCPtr &baseContainer)
{
S_D(ComplexTypeEntry);
d->m_baseContainerType = baseContainer;
}
-const ComplexTypeEntry *ComplexTypeEntry::baseContainerType() const
+ComplexTypeEntryCPtr ComplexTypeEntry::baseContainerType() const
{
S_D(const ComplexTypeEntry);
return d->m_baseContainerType;
@@ -1635,16 +1787,17 @@ TypeEntry *ComplexTypeEntry::clone() const
}
// Take over parameters relevant for typedefs
-void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntry *source)
+void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntryCPtr &source)
{
S_D(ComplexTypeEntry);
TypeEntry::useAsTypedef(source);
d->m_qualifiedCppName = source->qualifiedCppName();
d->m_targetType = source->targetType();
+ d->m_typeFlags.setFlag(ComplexTypeEntry::Typedef);
}
ComplexTypeEntry::ComplexTypeEntry(ComplexTypeEntryPrivate *d) :
- TypeEntry(d)
+ ConfigurableTypeEntry(d)
{
}
@@ -1663,7 +1816,7 @@ public:
TypedefEntryPrivate(const QString &entryName,
const QString &sourceType,
const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
ComplexTypeEntryPrivate(entryName, TypeEntry::TypedefType,
vr, parent),
m_sourceType(sourceType)
@@ -1671,12 +1824,12 @@ public:
}
QString m_sourceType;
- const ComplexTypeEntry *m_source = nullptr;
- ComplexTypeEntry *m_target = nullptr;
+ ComplexTypeEntryCPtr m_source;
+ ComplexTypeEntryPtr m_target;
};
TypedefEntry::TypedefEntry(const QString &entryName, const QString &sourceType,
- const QVersionNumber &vr, const TypeEntry *parent) :
+ const QVersionNumber &vr, const TypeEntryCPtr &parent) :
ComplexTypeEntry(new TypedefEntryPrivate(entryName, sourceType, vr, parent))
{
}
@@ -1699,25 +1852,25 @@ TypeEntry *TypedefEntry::clone() const
return new TypedefEntry(new TypedefEntryPrivate(*d));
}
-const ComplexTypeEntry *TypedefEntry::source() const
+ComplexTypeEntryCPtr TypedefEntry::source() const
{
S_D(const TypedefEntry);
return d->m_source;
}
-void TypedefEntry::setSource(const ComplexTypeEntry *source)
+void TypedefEntry::setSource(const ComplexTypeEntryCPtr &source)
{
S_D(TypedefEntry);
d->m_source = source;
}
-ComplexTypeEntry *TypedefEntry::target() const
+ComplexTypeEntryPtr TypedefEntry::target() const
{
S_D(const TypedefEntry);
return d->m_target;
}
-void TypedefEntry::setTarget(ComplexTypeEntry *target)
+void TypedefEntry::setTarget(ComplexTypeEntryPtr target)
{
S_D(TypedefEntry);
d->m_target = target;
@@ -1732,33 +1885,44 @@ TypedefEntry::TypedefEntry(TypedefEntryPrivate *d) :
class ContainerTypeEntryPrivate : public ComplexTypeEntryPrivate
{
public:
- using OpaqueContainer = ContainerTypeEntry::OpaqueContainer;
- using OpaqueContainers = ContainerTypeEntry::OpaqueContainers;
-
ContainerTypeEntryPrivate(const QString &entryName,
ContainerTypeEntry::ContainerKind containerKind,
const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
ComplexTypeEntryPrivate(entryName, TypeEntry::ContainerType, vr, parent),
m_containerKind(containerKind)
{
}
- OpaqueContainers::const_iterator findOpaqueContainer(const QString &instantiation) const
+ OpaqueContainers::const_iterator findOpaqueContainer(const QStringList &instantiations) const
{
return std::find_if(m_opaqueContainers.cbegin(), m_opaqueContainers.cend(),
- [&instantiation](const OpaqueContainer &r) {
- return r.instantiation == instantiation;
+ [&instantiations](const OpaqueContainer &r) {
+ return r.instantiations == instantiations;
});
}
OpaqueContainers m_opaqueContainers;
+ CustomConversionPtr m_customConversion;
ContainerTypeEntry::ContainerKind m_containerKind;
};
+QString OpaqueContainer::templateParameters() const
+{
+ QString result;
+ result += u'<';
+ for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) {
+ if (i)
+ result += u',';
+ result += instantiations.at(i);
+ }
+ result += u'>';
+ return result;
+}
+
ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, ContainerKind containerKind,
const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
ComplexTypeEntry(new ContainerTypeEntryPrivate(entryName, containerKind, vr, parent))
{
setCodeGeneration(GenerateForSubclass);
@@ -1770,36 +1934,67 @@ ContainerTypeEntry::ContainerKind ContainerTypeEntry::containerKind() const
return d->m_containerKind;
}
-const ContainerTypeEntry::OpaqueContainers &ContainerTypeEntry::opaqueContainers() const
+qsizetype ContainerTypeEntry::templateParameterCount() const
+{
+ S_D(const ContainerTypeEntry);
+ qsizetype result = 1;
+ switch (d->m_containerKind) {
+ case MapContainer:
+ case MultiMapContainer:
+ case PairContainer:
+ case SpanContainer:
+ result = 2;
+ break;
+ case ListContainer:
+ case SetContainer:
+ break;
+ }
+ return result;
+}
+
+const OpaqueContainers &ContainerTypeEntry::opaqueContainers() const
{
S_D(const ContainerTypeEntry);
return d->m_opaqueContainers;
}
-void ContainerTypeEntry::addOpaqueContainer(OpaqueContainer r)
+void ContainerTypeEntry::appendOpaqueContainers(const OpaqueContainers &l)
{
S_D(ContainerTypeEntry);
- // Fix to match AbstractMetaType::signature() which is used for matching
- // "Foo*" -> "Foo *"
- const auto asteriskPos = r.instantiation.indexOf(u'*');
- if (asteriskPos > 0 && !r.instantiation.at(asteriskPos - 1).isSpace())
- r.instantiation.insert(asteriskPos, u' ');
- d->m_opaqueContainers.append(r);
+ d->m_opaqueContainers.append(l);
}
-bool ContainerTypeEntry::generateOpaqueContainer(const QString &instantiation) const
+bool ContainerTypeEntry::generateOpaqueContainer(const QStringList &instantiations) const
{
S_D(const ContainerTypeEntry);
- return d->findOpaqueContainer(instantiation) != d->m_opaqueContainers.cend();
+ return d->findOpaqueContainer(instantiations) != d->m_opaqueContainers.cend();
}
-QString ContainerTypeEntry::opaqueContainerName(const QString &instantiation) const
+QString ContainerTypeEntry::opaqueContainerName(const QStringList &instantiations) const
{
S_D(const ContainerTypeEntry);
- const auto it = d->findOpaqueContainer(instantiation);
+ const auto it = d->findOpaqueContainer(instantiations);
return it != d->m_opaqueContainers.cend() ? it->name : QString{};
}
+bool ContainerTypeEntry::hasCustomConversion() const
+{
+ S_D(const ContainerTypeEntry);
+ return bool(d->m_customConversion);
+}
+
+void ContainerTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
+{
+ S_D(ContainerTypeEntry);
+ d->m_customConversion = customConversion;
+}
+
+CustomConversionPtr ContainerTypeEntry::customConversion() const
+{
+ S_D(const ContainerTypeEntry);
+ return d->m_customConversion;
+}
+
TypeEntry *ContainerTypeEntry::clone() const
{
S_D(const ContainerTypeEntry);
@@ -1819,7 +2014,7 @@ public:
const QString &getterName,
TypeSystem::SmartPointerType type,
const QString &refCountMethodName,
- const QVersionNumber &vr, const TypeEntry *parent) :
+ const QVersionNumber &vr, const TypeEntryCPtr &parent) :
ComplexTypeEntryPrivate(entryName, TypeEntry::SmartPointerType, vr, parent),
m_getterName(getterName),
m_refCountMethodName(refCountMethodName),
@@ -1827,6 +2022,8 @@ public:
{
}
+ qsizetype instantiationIndex(const TypeEntryCPtr &t) const;
+
QString m_getterName;
QString m_refCountMethodName;
QString m_valueCheckMethod;
@@ -1836,11 +2033,21 @@ public:
TypeSystem::SmartPointerType m_smartPointerType;
};
+qsizetype SmartPointerTypeEntryPrivate::instantiationIndex(const TypeEntryCPtr &t) const
+{
+ for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) {
+ if (m_instantiations.at(i).typeEntry == t)
+ return i;
+ }
+ return -1;
+}
+
SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &entryName,
const QString &getterName,
TypeSystem::SmartPointerType smartPointerType,
const QString &refCountMethodName,
- const QVersionNumber &vr, const TypeEntry *parent) :
+ const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
ComplexTypeEntry(new SmartPointerTypeEntryPrivate(entryName, getterName, smartPointerType,
refCountMethodName, vr, parent))
{
@@ -1906,7 +2113,7 @@ TypeEntry *SmartPointerTypeEntry::clone() const
return new SmartPointerTypeEntry(new SmartPointerTypeEntryPrivate(*d));
}
-SmartPointerTypeEntry::Instantiations SmartPointerTypeEntry::instantiations() const
+const SmartPointerTypeEntry::Instantiations &SmartPointerTypeEntry::instantiations() const
{
S_D(const SmartPointerTypeEntry);
return d->m_instantiations;
@@ -1923,10 +2130,11 @@ SmartPointerTypeEntry::SmartPointerTypeEntry(SmartPointerTypeEntryPrivate *d) :
{
}
-bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntry *e) const
+bool SmartPointerTypeEntry::matchesInstantiation(const TypeEntryCPtr &e) const
{
S_D(const SmartPointerTypeEntry);
- return d->m_instantiations.isEmpty() || d->m_instantiations.contains(e);
+ // No instantiations specified, or match
+ return d->m_instantiations.isEmpty() || d->instantiationIndex(e) != -1;
}
static QString fixSmartPointerName(QString name)
@@ -1938,18 +2146,14 @@ static QString fixSmartPointerName(QString name)
return name;
}
-QString SmartPointerTypeEntry::getTargetFullName(const AbstractMetaType &metaType,
- bool includePackageName)
+QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType) const
{
- QString result;
- if (includePackageName)
- result += metaType.package() + u'.';
- result += fixSmartPointerName(metaType.cppSignature());
- return result;
-}
+ S_D(const SmartPointerTypeEntry);
+ auto instantiatedTe = metaType.instantiations().constFirst().typeEntry();
+ const auto index = d->instantiationIndex(instantiatedTe);
+ if (index != -1 && !d->m_instantiations.at(index).name.isEmpty())
+ return d->m_instantiations.at(index).name;
-QString SmartPointerTypeEntry::getTargetName(const AbstractMetaType &metaType)
-{
QString name = metaType.cppSignature();
const auto templatePos = name.indexOf(u'<');
if (templatePos != -1) { // "std::shared_ptr<A::B>" -> "shared_ptr<A::B>"
@@ -1967,7 +2171,7 @@ public:
using ComplexTypeEntryPrivate::ComplexTypeEntryPrivate;
QRegularExpression m_filePattern;
- const NamespaceTypeEntry *m_extends = nullptr;
+ NamespaceTypeEntryCPtr m_extends;
TypeSystem::Visibility m_visibility = TypeSystem::Visibility::Auto;
bool m_hasPattern = false;
bool m_inlineNamespace = false;
@@ -1975,7 +2179,7 @@ public:
};
NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
ComplexTypeEntry(new NamespaceTypeEntryPrivate(entryName, NamespaceType, vr, parent))
{
}
@@ -1986,13 +2190,13 @@ TypeEntry *NamespaceTypeEntry::clone() const
return new NamespaceTypeEntry(new NamespaceTypeEntryPrivate(*d));
}
-const NamespaceTypeEntry *NamespaceTypeEntry::extends() const
+NamespaceTypeEntryCPtr NamespaceTypeEntry::extends() const
{
S_D(const NamespaceTypeEntry);
return d->m_extends;
}
-void NamespaceTypeEntry::setExtends(const NamespaceTypeEntry *e)
+void NamespaceTypeEntry::setExtends(const NamespaceTypeEntryCPtr &e)
{
S_D(NamespaceTypeEntry);
d->m_extends = e;
@@ -2055,6 +2259,11 @@ void NamespaceTypeEntry::setInlineNamespace(bool i)
d->m_inlineNamespace = i;
}
+bool NamespaceTypeEntry::isVisibleScope(const TypeEntryCPtr &e)
+{
+ return isVisibleScope(e.get());
+}
+
bool NamespaceTypeEntry::isVisibleScope(const TypeEntry *e)
{
return e->type() != TypeEntry::NamespaceType
@@ -2074,180 +2283,78 @@ void NamespaceTypeEntry::setGenerateUsing(bool generateUsing)
}
// ----------------- ValueTypeEntry
-ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent) :
- ComplexTypeEntry(entryName, BasicValueType, vr, parent)
-{
-}
-bool ValueTypeEntry::isValue() const
+class ValueTypeEntryPrivate : public ComplexTypeEntryPrivate
{
- return true;
-}
-
-TypeEntry *ValueTypeEntry::clone() const
-{
- S_D(const ComplexTypeEntry);
- return new ValueTypeEntry(new ComplexTypeEntryPrivate(*d));
-}
-
-ValueTypeEntry::ValueTypeEntry(ComplexTypeEntryPrivate *d) :
- ComplexTypeEntry(d)
-{
-}
-
-ValueTypeEntry::ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr,
- const TypeEntry *parent) :
- ComplexTypeEntry(entryName, t, vr, parent)
-{
-}
-
-// ----------------- CustomConversion
-struct CustomConversion::CustomConversionPrivate
-{
- CustomConversionPrivate(const TypeEntry* ownerType)
- : ownerType(ownerType), replaceOriginalTargetToNativeConversions(false)
- {
- }
- const TypeEntry* ownerType;
- QString nativeToTargetConversion;
- bool replaceOriginalTargetToNativeConversions;
- TargetToNativeConversions targetToNativeConversions;
-};
+public:
+ using ComplexTypeEntryPrivate::ComplexTypeEntryPrivate;
-struct CustomConversion::TargetToNativeConversion::TargetToNativeConversionPrivate
-{
- TargetToNativeConversionPrivate()
- : sourceType(nullptr)
- {
- }
- const TypeEntry* sourceType;
- QString sourceTypeName;
- QString sourceTypeCheck;
- QString conversion;
+ QString m_targetConversionRule;
+ CustomConversionPtr m_customConversion;
};
-CustomConversion::CustomConversion(TypeEntry* ownerType)
-{
- m_d = new CustomConversionPrivate(ownerType);
- if (ownerType)
- ownerType->setCustomConversion(this);
-}
-
-CustomConversion::~CustomConversion()
-{
- qDeleteAll(m_d->targetToNativeConversions);
- delete m_d;
-}
-
-const TypeEntry* CustomConversion::ownerType() const
-{
- return m_d->ownerType;
-}
-
-QString CustomConversion::nativeToTargetConversion() const
-{
- return m_d->nativeToTargetConversion;
-}
-
-void CustomConversion::setNativeToTargetConversion(const QString& nativeToTargetConversion)
-{
- m_d->nativeToTargetConversion = nativeToTargetConversion;
-}
-
-bool CustomConversion::replaceOriginalTargetToNativeConversions() const
-{
- return m_d->replaceOriginalTargetToNativeConversions;
-}
-
-void CustomConversion::setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions)
-{
- m_d->replaceOriginalTargetToNativeConversions = replaceOriginalTargetToNativeConversions;
-}
-
-bool CustomConversion::hasTargetToNativeConversions() const
-{
- return !(m_d->targetToNativeConversions.isEmpty());
-}
-
-CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions()
+ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
+ ComplexTypeEntry(new ValueTypeEntryPrivate(entryName, BasicValueType, vr, parent))
{
- return m_d->targetToNativeConversions;
}
-const CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions() const
+bool ValueTypeEntry::hasCustomConversion() const
{
- return m_d->targetToNativeConversions;
+ S_D(const ValueTypeEntry);
+ return bool(d->m_customConversion);
}
-void CustomConversion::addTargetToNativeConversion(const QString& sourceTypeName,
- const QString& sourceTypeCheck,
- const QString& conversion)
+void ValueTypeEntry::setCustomConversion(const CustomConversionPtr &customConversion)
{
- m_d->targetToNativeConversions.append(new TargetToNativeConversion(sourceTypeName, sourceTypeCheck, conversion));
+ S_D(ValueTypeEntry);
+ d->m_customConversion = customConversion;
}
-CustomConversion::TargetToNativeConversion::TargetToNativeConversion(const QString& sourceTypeName,
- const QString& sourceTypeCheck,
- const QString& conversion)
+CustomConversionPtr ValueTypeEntry::customConversion() const
{
- m_d = new TargetToNativeConversionPrivate;
- m_d->sourceTypeName = sourceTypeName;
- m_d->sourceTypeCheck = sourceTypeCheck;
- m_d->conversion = conversion;
+ S_D(const ValueTypeEntry);
+ return d->m_customConversion;
}
-CustomConversion::TargetToNativeConversion::~TargetToNativeConversion()
+void ValueTypeEntry::setTargetConversionRule(const QString &conversionRule)
{
- delete m_d;
+ S_D(ValueTypeEntry);
+ d->m_targetConversionRule = conversionRule;
}
-const TypeEntry* CustomConversion::TargetToNativeConversion::sourceType() const
+QString ValueTypeEntry::targetConversionRule() const
{
- return m_d->sourceType;
+ S_D(const ValueTypeEntry);
+ return d->m_targetConversionRule;
}
-void CustomConversion::TargetToNativeConversion::setSourceType(const TypeEntry* sourceType)
+bool ValueTypeEntry::hasTargetConversionRule() const
{
- m_d->sourceType = sourceType;
+ S_D(const ValueTypeEntry);
+ return !d->m_targetConversionRule.isEmpty();
}
-bool CustomConversion::TargetToNativeConversion::isCustomType() const
+bool ValueTypeEntry::isValue() const
{
- return !(m_d->sourceType);
+ return true;
}
-QString CustomConversion::TargetToNativeConversion::sourceTypeName() const
+TypeEntry *ValueTypeEntry::clone() const
{
- return m_d->sourceTypeName;
+ S_D(const ValueTypeEntry);
+ return new ValueTypeEntry(new ValueTypeEntryPrivate(*d));
}
-QString CustomConversion::TargetToNativeConversion::sourceTypeCheck() const
-{
- if (!m_d->sourceTypeCheck.isEmpty())
- return m_d->sourceTypeCheck;
-
- if (m_d->sourceType != nullptr && m_d->sourceType->isCustom()) {
- const auto *cte = static_cast<const CustomTypeEntry *>(m_d->sourceType);
- if (cte->hasCheckFunction()) {
- QString result = cte->checkFunction();
- if (result != u"true") // For PyObject, which is always true
- result += u"(%in)"_s;
- return result;
- }
- }
-
- return {};
-}
-
-QString CustomConversion::TargetToNativeConversion::conversion() const
+ValueTypeEntry::ValueTypeEntry(ComplexTypeEntryPrivate *d) :
+ ComplexTypeEntry(d)
{
- return m_d->conversion;
}
-void CustomConversion::TargetToNativeConversion::setConversion(const QString& conversion)
+ValueTypeEntry::ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr,
+ const TypeEntryCPtr &parent) :
+ ComplexTypeEntry(entryName, t, vr, parent)
{
- m_d->conversion = conversion;
}
// ----------------- FunctionTypeEntry
@@ -2256,19 +2363,19 @@ class FunctionTypeEntryPrivate : public TypeEntryPrivate
public:
FunctionTypeEntryPrivate(const QString &entryName, const QString &signature,
const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntryPrivate(entryName, TypeEntry::FunctionType, vr, parent),
m_signatures(signature)
{
}
QStringList m_signatures;
- TypeSystem::SnakeCase m_snakeCase = TypeSystem::SnakeCase::Unspecified;
+ QString m_docFile;
};
FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature,
const QVersionNumber &vr,
- const TypeEntry *parent) :
+ const TypeEntryCPtr &parent) :
TypeEntry(new FunctionTypeEntryPrivate(entryName, signature, vr, parent))
{
}
@@ -2291,16 +2398,16 @@ bool FunctionTypeEntry::hasSignature(const QString &signature) const
return d->m_signatures.contains(signature);
}
-TypeSystem::SnakeCase FunctionTypeEntry::snakeCase() const
+QString FunctionTypeEntry::docFile() const
{
S_D(const FunctionTypeEntry);
- return d->m_snakeCase;
+ return d->m_docFile;
}
-void FunctionTypeEntry::setSnakeCase(TypeSystem::SnakeCase sc)
+void FunctionTypeEntry::setDocFile(const QString &df)
{
S_D(FunctionTypeEntry);
- d->m_snakeCase = sc;
+ d->m_docFile = df;
}
TypeEntry *FunctionTypeEntry::clone() const
@@ -2316,7 +2423,7 @@ FunctionTypeEntry::FunctionTypeEntry(FunctionTypeEntryPrivate *d) :
// ----------------- ObjectTypeEntry
ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent)
+ const TypeEntryCPtr &parent)
: ComplexTypeEntry(entryName, ObjectType, vr, parent)
{
}
@@ -2346,20 +2453,6 @@ ObjectTypeEntry::ObjectTypeEntry(ComplexTypeEntryPrivate *d) :
if (!var.isEmpty()) \
debug << ", " << var.size() << ' ' << name;
-template <class Container, class Separator>
-static void formatList(QDebug &d, const char *name, const Container &c, Separator sep)
-{
- if (const int size = c.size()) {
- d << ", " << name << '[' << size << "]=(";
- for (int i = 0; i < size; ++i) {
- if (i)
- d << sep;
- d << c.at(i);
- }
- d << ')';
- }
-}
-
void TypeEntry::formatDebug(QDebug &debug) const
{
const QString cppName = qualifiedCppName();
@@ -2374,8 +2467,6 @@ void TypeEntry::formatDebug(QDebug &debug) const
FORMAT_NONEMPTY_STRING("package", m_d->m_targetLangPackage)
FORMAT_BOOL("stream", m_d->m_stream)
FORMAT_BOOL("built-in", m_d->m_builtin)
- FORMAT_LIST_SIZE("codeSnips", m_d->m_codeSnips)
- FORMAT_NONEMPTY_STRING("targetConversionRule", m_d->m_targetConversionRule)
if (m_d->m_viewOn)
debug << ", views=" << m_d->m_viewOn->name();
if (!m_d->m_version.isNull() && m_d->m_version > QVersionNumber(0, 0))
@@ -2394,9 +2485,9 @@ void TypeEntry::formatDebug(QDebug &debug) const
void PrimitiveTypeEntry::formatDebug(QDebug &debug) const
{
TypeEntry::formatDebug(debug);
- if (auto *e = referencedTypeEntry()) {
+ if (auto e = referencedTypeEntry()) {
debug << ", references";
- for (; e != nullptr; e = e->referencedTypeEntry())
+ for (; e ; e = e->referencedTypeEntry())
debug << ":\"" << e->qualifiedCppName() <<'"';
}
}
@@ -2420,6 +2511,7 @@ void ComplexTypeEntry::formatDebug(QDebug &debug) const
FORMAT_NONEMPTY_STRING("hash", d->m_hashFunction)
FORMAT_LIST_SIZE("addedFunctions", d->m_addedFunctions)
formatList(debug, "functionMods", d->m_functionMods, ", ");
+ FORMAT_LIST_SIZE("codeSnips", d->m_codeSnips)
FORMAT_LIST_SIZE("fieldMods", d->m_fieldMods)
}
@@ -2443,8 +2535,7 @@ void FunctionTypeEntry::formatDebug(QDebug &debug) const
S_D(const FunctionTypeEntry);
TypeEntry::formatDebug(debug);
- debug << "signatures=" << d->m_signatures
- << ", snakeCase=" << int(d->m_snakeCase);
+ debug << "signatures=" << d->m_signatures;
}
void TypedefEntry::formatDebug(QDebug &debug) const
@@ -2461,6 +2552,8 @@ void EnumTypeEntry::formatDebug(QDebug &debug) const
S_D(const EnumTypeEntry);
TypeEntry::formatDebug(debug);
+ if (d->m_pythonEnumType != TypeSystem::PythonEnumType::Unspecified)
+ debug << ", python-type=" << int(d->m_pythonEnumType);
if (d->m_flags)
debug << ", flags=(" << d->m_flags << ')';
}
@@ -2477,18 +2570,23 @@ void NamespaceTypeEntry::formatDebug(QDebug &debug) const
debug << "[inline]";
}
+QDebug operator<<(QDebug d, const OpaqueContainer &oc)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "OpaqueContainer(\"" << oc.name << "\": " << oc.templateParameters() << ')';
+ return d;
+}
+
void ContainerTypeEntry::formatDebug(QDebug &debug) const
{
S_D(const ContainerTypeEntry);
ComplexTypeEntry::formatDebug(debug);
debug << ", type=" << d->m_containerKind << '"';
- if (!d->m_opaqueContainers.isEmpty()) {
- debug << ", opaque-containers=[";
- for (const auto &r : d->m_opaqueContainers)
- debug << r.instantiation << "->" << r.name << ',';
- debug << ']';
- }
+ if (!d->m_opaqueContainers.isEmpty())
+ debug << ", opaque-containers=[" << d->m_opaqueContainers << ']';
}
void SmartPointerTypeEntry::formatDebug(QDebug &debug) const
@@ -2499,8 +2597,11 @@ void SmartPointerTypeEntry::formatDebug(QDebug &debug) const
if (!d->m_instantiations.isEmpty()) {
debug << "type=" << d->m_type << ", instantiations["
<< d->m_instantiations.size() << "]=(";
- for (auto i : d->m_instantiations)
- debug << i->name() << ',';
+ for (const auto &i : d->m_instantiations) {
+ debug << i.typeEntry->name() << ',';
+ if (!i.name.isEmpty())
+ debug << "=\"" << i.name << '"';
+ }
debug << ')';
}
}
@@ -2519,6 +2620,12 @@ QDebug operator<<(QDebug d, const TypeEntry *te)
return d;
}
+QDebug operator<<(QDebug d, const TypeEntryCPtr &te)
+{
+ d << te.get();
+ return d;
+}
+
QDebug operator<<(QDebug d, const TemplateEntry *te)
{
QDebugStateSaver saver(d);
@@ -2533,4 +2640,10 @@ QDebug operator<<(QDebug d, const TemplateEntry *te)
d << ')';
return d;
}
+
+QDebug operator<<(QDebug d, const TemplateEntryCPtr &te)
+{
+ d << te.get();
+ return d;
+}
#endif // QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h
index 186d82675..a2e4debc8 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.h
+++ b/sources/shiboken6/ApiExtractor/typesystem.h
@@ -4,15 +4,14 @@
#ifndef TYPESYSTEM_H
#define TYPESYSTEM_H
-#include "typesystem_enums.h"
-#include "typesystem_typedefs.h"
#include "include.h"
+#include "typesystem_typedefs.h"
+#include <QtCore/qobjectdefs.h>
#include <QtCore/QString>
#include <QtCore/QScopedPointer>
class AbstractMetaType;
-class CustomConversion;
class CustomTypeEntry;
class PrimitiveTypeEntry;
class SourceLocation;
@@ -63,17 +62,14 @@ public:
Q_ENUM(CodeGeneration)
explicit TypeEntry(const QString &entryName, Type t, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
virtual ~TypeEntry();
Type type() const;
- const TypeEntry *parent() const;
- void setParent(const TypeEntry *p);
- bool isChildOf(const TypeEntry *p) const;
- const TypeSystemTypeEntry *typeSystemTypeEntry() const;
- // cf AbstractMetaClass::targetLangEnclosingClass()
- const TypeEntry *targetLangEnclosingEntry() const;
+ TypeEntryCPtr parent() const;
+ void setParent(const TypeEntryCPtr &);
+ bool isChildOf(const TypeEntryCPtr &p) const;
bool isPrimitive() const;
bool isEnum() const;
@@ -134,9 +130,9 @@ public:
/// be a JNI name, for Python it should represent the CPython type name.
/// \return string representing the target language API name
/// Currently used only for PrimitiveTypeEntry (attribute "target").
- const CustomTypeEntry *targetLangApiType() const;
+ CustomTypeEntryCPtr targetLangApiType() const;
bool hasTargetLangApiType() const;
- void setTargetLangApiType(CustomTypeEntry *cte);
+ void setTargetLangApiType(const CustomTypeEntryPtr &cte);
QString targetLangApiName() const;
// The type's name in TargetLang
@@ -153,70 +149,32 @@ public:
virtual bool isValue() const;
virtual bool isComplex() const;
- const CodeSnipList &codeSnips() const;
- CodeSnipList &codeSnips();
- void setCodeSnips(const CodeSnipList &codeSnips);
- void addCodeSnip(const CodeSnip &codeSnip);
-
- void setDocModification(const DocModificationList& docMods);
- DocModificationList docModifications() const;
-
const IncludeList &extraIncludes() const;
void setExtraIncludes(const IncludeList &includes);
void addExtraInclude(const Include &newInclude);
- /// Extra includes for function arguments determined by the meta builder.
- const IncludeList &argumentIncludes() const;
- void addArgumentInclude(const Include &newInclude);
-
Include include() const;
void setInclude(const Include &inc);
- // FIXME PYSIDE7: Remove
- /// Set the target type conversion rule
- void setTargetConversionRule(const QString& conversionRule);
-
- /// Returns the target type conversion rule
- QString targetConversionRule() const;
-
QVersionNumber version() const;
- /// TODO-CONVERTER: mark as deprecated
- bool hasTargetConversionRule() const;
-
- bool isCppPrimitive() const;
-
- bool hasCustomConversion() const;
- void setCustomConversion(CustomConversion* customConversion);
- CustomConversion* customConversion() const;
-
// View on: Type to use for function argument conversion, fex
// std::string_view -> std::string for foo(std::string_view).
// cf AbstractMetaType::viewOn()
- TypeEntry *viewOn() const;
- void setViewOn(TypeEntry *v);
+ TypeEntryPtr viewOn() const;
+ void setViewOn(const TypeEntryPtr &v);
virtual TypeEntry *clone() const;
- void useAsTypedef(const TypeEntry *source);
+ void useAsTypedef(const TypeEntryCPtr &source);
SourceLocation sourceLocation() const;
void setSourceLocation(const SourceLocation &sourceLocation);
- const PrimitiveTypeEntry *asPrimitive() const;
-
// Query functions for generators
- /// Returns true if the type is a primitive but not a C++ primitive.
- bool isUserPrimitive() const;
/// Returns true if the type passed has a Python wrapper for it.
/// Although namespace has a Python wrapper, it's not considered a type.
bool isWrapperType() const;
- /// Returns true if the type is a C++ integral primitive,
- /// i.e. bool, char, int, long, and their unsigned counterparts.
- bool isCppIntegralPrimitive() const;
- /// Returns true if the type is an extended C++ primitive, a void*,
- /// a const char*, or a std::string (cf isCppPrimitive()).
- bool isExtendedCppPrimitive() const;
#ifndef QT_NO_DEBUG_STREAM
virtual void formatDebug(QDebug &d) const;
@@ -236,4 +194,22 @@ private:
QScopedPointer<TypeEntryPrivate> m_d;
};
+TypeSystemTypeEntryCPtr typeSystemTypeEntry(TypeEntryCPtr e);
+
+// cf AbstractMetaClass::targetLangEnclosingClass()
+TypeEntryCPtr targetLangEnclosingEntry(const TypeEntryCPtr &e);
+
+bool isCppPrimitive(const TypeEntryCPtr &e);
+
+/// Returns true if the type is a primitive but not a C++ primitive.
+bool isUserPrimitive(const TypeEntryCPtr &e);
+
+/// Returns true if the type is a C++ integral primitive,
+/// i.e. bool, char, int, long, and their unsigned counterparts.
+bool isCppIntegralPrimitive(const TypeEntryCPtr &e);
+
+/// Returns true if the type is an extended C++ primitive, a void*,
+/// a const char*, or a std::string (cf isCppPrimitive()).
+bool isExtendedCppPrimitive(const TypeEntryCPtr &e);
+
#endif // TYPESYSTEM_H
diff --git a/sources/shiboken6/ApiExtractor/typesystem_enums.h b/sources/shiboken6/ApiExtractor/typesystem_enums.h
index 58c40b3d0..9ecbb08a1 100644
--- a/sources/shiboken6/ApiExtractor/typesystem_enums.h
+++ b/sources/shiboken6/ApiExtractor/typesystem_enums.h
@@ -35,6 +35,7 @@ enum CodeSnipPosition {
CodeSnipPositionBeginning,
CodeSnipPositionEnd,
CodeSnipPositionDeclaration,
+ CodeSnipPositionPyOverride,
CodeSnipPositionAny
};
@@ -97,6 +98,14 @@ enum class SmartPointerType {
ValueHandle
};
+enum class PythonEnumType {
+ Unspecified,
+ Enum,
+ IntEnum,
+ Flag,
+ IntFlag
+};
+
enum : int { OverloadNumberUnset = -1, OverloadNumberDefault = 99999 };
} // namespace TypeSystem
diff --git a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h
index 3c1ad53f8..5a4e12ff2 100644
--- a/sources/shiboken6/ApiExtractor/typesystem_typedefs.h
+++ b/sources/shiboken6/ApiExtractor/typesystem_typedefs.h
@@ -4,24 +4,76 @@
#ifndef TYPESYSTEM_TYPEDEFS_H
#define TYPESYSTEM_TYPEDEFS_H
-#include <QtCore/QHash>
-#include <QtCore/QList>
-#include <QtCore/QSharedPointer>
#include <QtCore/QList>
-class CodeSnip;
-class DocModification;
+#include <memory>
-struct AddedFunction;
-class FieldModification;
-class FunctionModification;
+class ArrayTypeEntry;
+class ComplexTypeEntry;
+class ConfigurableTypeEntry;
+class ConstantValueTypeEntry;
+class ContainerTypeEntry;
+class CustomTypeEntry;
+class EnumTypeEntry;
+class EnumValueTypeEntry;
+class FlagsTypeEntry;
+class FunctionTypeEntry;
+class NamespaceTypeEntry;
+class ObjectTypeEntry;
+class PrimitiveTypeEntry;
+class SmartPointerTypeEntry;
+class TemplateEntry;
class TypeEntry;
+class TypedefEntry;
+class TypeSystemTypeEntry;
+class ValueTypeEntry;
+
+using ArrayTypeEntryPtr = std::shared_ptr<ArrayTypeEntry>;
+using ComplexTypeEntryPtr = std::shared_ptr<ComplexTypeEntry>;
+using ConfigurableTypeEntryPtr = std::shared_ptr<ConfigurableTypeEntry>;
+using ConstantValueTypeEntryPtr = std::shared_ptr<ConstantValueTypeEntry>;
+using ContainerTypeEntryPtr = std::shared_ptr<ContainerTypeEntry>;
+using CustomTypeEntryPtr = std::shared_ptr<CustomTypeEntry>;
+using EnumTypeEntryPtr = std::shared_ptr<EnumTypeEntry>;
+using EnumValueTypeEntryPtr = std::shared_ptr<EnumValueTypeEntry>;
+using FlagsTypeEntryPtr = std::shared_ptr<FlagsTypeEntry>;
+using FunctionTypeEntryPtr = std::shared_ptr<FunctionTypeEntry>;
+using NamespaceTypeEntryPtr = std::shared_ptr<NamespaceTypeEntry>;
+using ObjectTypeEntryPtr = std::shared_ptr<ObjectTypeEntry>;
+using PrimitiveTypeEntryPtr = std::shared_ptr<PrimitiveTypeEntry>;
+using SmartPointerTypeEntryPtr = std::shared_ptr<SmartPointerTypeEntry>;
+using TemplateEntryPtr = std::shared_ptr<TemplateEntry>;
+using TypeEntryPtr = std::shared_ptr<TypeEntry>;
+using TypedefEntryPtr = std::shared_ptr<TypedefEntry>;
+using TypeSystemTypeEntryPtr = std::shared_ptr<TypeSystemTypeEntry>;
+using ValueTypeEntryPtr = std::shared_ptr<ValueTypeEntry>;
+
+using ArrayTypeEntryCPtr = std::shared_ptr<const ArrayTypeEntry>;
+using ComplexTypeEntryCPtr = std::shared_ptr<const ComplexTypeEntry>;
+using ConstantValueTypeEntryCPtr = std::shared_ptr<const ConstantValueTypeEntry>;
+using ConfigurableTypeEntryCPtr = std::shared_ptr<const ConfigurableTypeEntry>;
+using ContainerTypeEntryCPtr = std::shared_ptr<const ContainerTypeEntry>;
+using CustomTypeEntryCPtr = std::shared_ptr<const CustomTypeEntry>;
+using EnumTypeEntryCPtr = std::shared_ptr<const EnumTypeEntry>;
+using EnumValueTypeEntryCPtr = std::shared_ptr<const EnumValueTypeEntry>;
+using FlagsTypeEntryCPtr = std::shared_ptr<const FlagsTypeEntry>;
+using FunctionTypeEntryCPtr = std::shared_ptr<const FunctionTypeEntry>;
+using NamespaceTypeEntryCPtr = std::shared_ptr<const NamespaceTypeEntry>;
+using ObjectTypeEntryCPtr = std::shared_ptr<const ObjectTypeEntry>;
+using PrimitiveTypeEntryCPtr = std::shared_ptr<const PrimitiveTypeEntry>;
+using SmartPointerTypeEntryCPtr = std::shared_ptr<const SmartPointerTypeEntry>;
+using TemplateEntryCPtr = std::shared_ptr<const TemplateEntry>;
+using TypeEntryCPtr = std::shared_ptr<const TypeEntry>;
+using TypedefEntryCPtr = std::shared_ptr<const TypedefEntry>;
+using TypeSystemTypeEntryCPtr = std::shared_ptr<const TypeSystemTypeEntry>;
+using ValueTypeEntryCPtr = std::shared_ptr<const ValueTypeEntry>;
+
+using ComplexTypeEntryCList = QList<ComplexTypeEntryCPtr>;
+using ContainerTypeEntryCList = QList<ContainerTypeEntryCPtr>;
+using NamespaceTypeEntryList = QList<NamespaceTypeEntryPtr>;
+using PrimitiveTypeEntryCList = QList<PrimitiveTypeEntryCPtr>;
+using SmartPointerTypeEntryList = QList<SmartPointerTypeEntryCPtr>;
+using TypeEntryList = QList<TypeEntryPtr>;
+using TypeEntryCList = QList<TypeEntryCPtr>;
-using AddedFunctionPtr = QSharedPointer<AddedFunction>;
-using AddedFunctionList = QList<AddedFunctionPtr>;
-using CodeSnipList = QList<CodeSnip>;
-using DocModificationList = QList<DocModification>;
-using FieldModificationList = QList<FieldModification>;
-using FunctionModificationList = QList<FunctionModification>;
-using TypeEntries = QList<const TypeEntry *>;
#endif // TYPESYSTEM_TYPEDEFS_H
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index d91fa9193..2b686e997 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -2,22 +2,19 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "typesystemparser_p.h"
+#include "anystringview_helpers.h"
+#include "addedfunction.h"
#include "codesnip.h"
#include "enumtypeentry.h"
-#include "enumvaluetypeentry.h"
-#include "arraytypeentry.h"
-#include "constantvaluetypeentry.h"
#include "containertypeentry.h"
#include "customconversion.h"
#include "customtypenentry.h"
-#include "enumtypeentry.h"
#include "flagstypeentry.h"
#include "functiontypeentry.h"
#include "namespacetypeentry.h"
#include "objecttypeentry.h"
#include "primitivetypeentry.h"
#include "smartpointertypeentry.h"
-#include "templateargumententry.h"
#include "typedefentry.h"
#include "typesystemtypeentry.h"
#include "valuetypeentry.h"
@@ -49,76 +46,84 @@
using namespace Qt::StringLiterals;
-static inline QString allowThreadAttribute() { return QStringLiteral("allow-thread"); }
-static inline QString colonColon() { return QStringLiteral("::"); }
-static inline QString checkFunctionAttribute() { return QStringLiteral("check-function"); }
-static inline QString copyableAttribute() { return QStringLiteral("copyable"); }
-static inline QString accessAttribute() { return QStringLiteral("access"); }
-static inline QString actionAttribute() { return QStringLiteral("action"); }
-static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); }
-static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); }
-static inline QString textAttribute() { return QStringLiteral("text"); }
-static inline QString nameAttribute() { return QStringLiteral("name"); }
-static inline QString sinceAttribute() { return QStringLiteral("since"); }
-static inline QString untilAttribute() { return QStringLiteral("until"); }
-static inline QString defaultSuperclassAttribute() { return QStringLiteral("default-superclass"); }
-static inline QString deleteInMainThreadAttribute() { return QStringLiteral("delete-in-main-thread"); }
-static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); }
-static inline QString disableWrapperAttribute() { return QStringLiteral("disable-wrapper"); }
-static inline QString exceptionHandlingAttribute() { return QStringLiteral("exception-handling"); }
-static inline QString extensibleAttribute() { return QStringLiteral("extensible"); }
-static inline QString fileNameAttribute() { return QStringLiteral("file-name"); }
-static inline QString flagsAttribute() { return QStringLiteral("flags"); }
-static inline QString forceAbstractAttribute() { return QStringLiteral("force-abstract"); }
-static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); }
-static inline QString formatAttribute() { return QStringLiteral("format"); }
-static inline QString generateUsingAttribute() { return QStringLiteral("generate-using"); }
-static inline QString generateFunctionsAttribute() { return QStringLiteral("generate-functions"); }
-static inline QString classAttribute() { return QStringLiteral("class"); }
-static inline QString generateAttribute() { return QStringLiteral("generate"); }
-static inline QString generateGetSetDefAttribute() { return QStringLiteral("generate-getsetdef"); }
-static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); }
-static inline QString indexAttribute() { return QStringLiteral("index"); }
-static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); }
-static inline QString isNullAttribute() { return QStringLiteral("isNull"); }
-static inline QString locationAttribute() { return QStringLiteral("location"); }
-static inline QString modifiedTypeAttribute() { return QStringLiteral("modified-type"); }
-static inline QString operatorBoolAttribute() { return QStringLiteral("operator-bool"); }
-static inline QString parentManagementAttribute() { return QStringLiteral("parent-management"); }
-static inline QString pyiTypeAttribute() { return QStringLiteral("pyi-type"); }
-static inline QString overloadNumberAttribute() { return QStringLiteral("overload-number"); }
-static inline QString ownershipAttribute() { return QStringLiteral("owner"); }
-static inline QString packageAttribute() { return QStringLiteral("package"); }
-static inline QString positionAttribute() { return QStringLiteral("position"); }
-static inline QString preferredConversionAttribute() { return QStringLiteral("preferred-conversion"); }
-static inline QString preferredTargetLangTypeAttribute() { return QStringLiteral("preferred-target-lang-type"); }
-static inline QString qtMetaTypeAttribute() { return QStringLiteral("qt-register-metatype"); }
-static inline QString removeAttribute() { return QStringLiteral("remove"); }
-static inline QString renameAttribute() { return QStringLiteral("rename"); }
-static inline QString readAttribute() { return QStringLiteral("read"); }
-static inline QString targetLangNameAttribute() { return QStringLiteral("target-lang-name"); }
-static inline QString writeAttribute() { return QStringLiteral("write"); }
-static inline QString opaqueContainerFieldAttribute() { return QStringLiteral("opaque-container"); }
-static inline QString replaceAttribute() { return QStringLiteral("replace"); }
-static inline QString toAttribute() { return QStringLiteral("to"); }
-static inline QString signatureAttribute() { return QStringLiteral("signature"); }
-static inline QString snippetAttribute() { return QStringLiteral("snippet"); }
-static inline QString snakeCaseAttribute() { return QStringLiteral("snake-case"); }
-static inline QString staticAttribute() { return QStringLiteral("static"); }
-static inline QString classmethodAttribute() { return QStringLiteral("classmethod"); }
-static inline QString threadAttribute() { return QStringLiteral("thread"); }
-static inline QString sourceAttribute() { return QStringLiteral("source"); }
-static inline QString streamAttribute() { return QStringLiteral("stream"); }
-static inline QString privateAttribute() { return QStringLiteral("private"); }
-static inline QString xPathAttribute() { return QStringLiteral("xpath"); }
-static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); }
-static inline QString visibleAttribute() { return QStringLiteral("visible"); }
-static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); }
-
-static inline QString noAttributeValue() { return QStringLiteral("no"); }
-static inline QString yesAttributeValue() { return QStringLiteral("yes"); }
-static inline QString trueAttributeValue() { return QStringLiteral("true"); }
-static inline QString falseAttributeValue() { return QStringLiteral("false"); }
+constexpr auto allowThreadAttribute = "allow-thread"_L1;
+constexpr auto checkFunctionAttribute = "check-function"_L1;
+constexpr auto copyableAttribute = "copyable"_L1;
+constexpr auto accessAttribute = "access"_L1;
+constexpr auto actionAttribute = "action"_L1;
+constexpr auto quoteAfterLineAttribute = "quote-after-line"_L1;
+constexpr auto quoteBeforeLineAttribute = "quote-before-line"_L1;
+constexpr auto textAttribute = "text"_L1;
+constexpr auto nameAttribute = "name"_L1;
+constexpr auto sinceAttribute = "since"_L1;
+constexpr auto untilAttribute = "until"_L1;
+constexpr auto defaultSuperclassAttribute = "default-superclass"_L1;
+constexpr auto deleteInMainThreadAttribute = "delete-in-main-thread"_L1;
+constexpr auto deprecatedAttribute = "deprecated"_L1;
+constexpr auto disableWrapperAttribute = "disable-wrapper"_L1;
+constexpr auto docFileAttribute = "doc-file"_L1;
+constexpr auto exceptionHandlingAttribute = "exception-handling"_L1;
+constexpr auto extensibleAttribute = "extensible"_L1;
+constexpr auto fileNameAttribute = "file-name"_L1;
+constexpr auto fileAttribute = "file"_L1;
+constexpr auto flagsAttribute = "flags"_L1;
+constexpr auto forceAbstractAttribute = "force-abstract"_L1;
+constexpr auto forceIntegerAttribute = "force-integer"_L1;
+constexpr auto formatAttribute = "format"_L1;
+constexpr auto generateUsingAttribute = "generate-using"_L1;
+constexpr auto generateFunctionsAttribute = "generate-functions"_L1;
+constexpr auto classAttribute = "class"_L1;
+constexpr auto generateAttribute = "generate"_L1;
+constexpr auto generateGetSetDefAttribute = "generate-getsetdef"_L1;
+constexpr auto genericClassAttribute = "generic-class"_L1;
+constexpr auto indexAttribute = "index"_L1;
+constexpr auto invalidateAfterUseAttribute = "invalidate-after-use"_L1;
+constexpr auto isNullAttribute = "isNull"_L1;
+constexpr auto locationAttribute = "location"_L1;
+constexpr auto modifiedTypeAttribute = "modified-type"_L1;
+constexpr auto opaqueContainerAttribute = "opaque-containers"_L1;
+constexpr auto operatorBoolAttribute = "operator-bool"_L1;
+constexpr auto parentManagementAttribute = "parent-management"_L1;
+constexpr auto pyiTypeAttribute = "pyi-type"_L1;
+constexpr auto overloadNumberAttribute = "overload-number"_L1;
+constexpr auto ownershipAttribute = "owner"_L1;
+constexpr auto packageAttribute = "package"_L1;
+constexpr auto polymorphicBaseAttribute = "polymorphic-base"_L1;
+constexpr auto positionAttribute = "position"_L1;
+constexpr auto preferredConversionAttribute = "preferred-conversion"_L1;
+constexpr auto preferredTargetLangTypeAttribute = "preferred-target-lang-type"_L1;
+constexpr auto pythonEnumTypeAttribute = "python-type"_L1;
+constexpr auto pythonOverrideAttribute = "python-override"_L1;
+constexpr auto cppEnumTypeAttribute = "cpp-type"_L1;
+constexpr auto qtMetaObjectFunctionsAttribute = "qt-metaobject"_L1;
+constexpr auto qtMetaTypeAttribute = "qt-register-metatype"_L1;
+constexpr auto removeAttribute = "remove"_L1;
+constexpr auto renameAttribute = "rename"_L1;
+constexpr auto readAttribute = "read"_L1;
+constexpr auto targetLangNameAttribute = "target-lang-name"_L1;
+constexpr auto writeAttribute = "write"_L1;
+constexpr auto opaqueContainerFieldAttribute = "opaque-container"_L1;
+constexpr auto replaceAttribute = "replace"_L1;
+constexpr auto toAttribute = "to"_L1;
+constexpr auto signatureAttribute = "signature"_L1;
+constexpr auto snippetAttribute = "snippet"_L1;
+constexpr auto snakeCaseAttribute = "snake-case"_L1;
+constexpr auto staticAttribute = "static"_L1;
+constexpr auto classmethodAttribute = "classmethod"_L1;
+constexpr auto threadAttribute = "thread"_L1;
+constexpr auto sourceAttribute = "source"_L1;
+constexpr auto streamAttribute = "stream"_L1;
+constexpr auto privateAttribute = "private"_L1;
+constexpr auto xPathAttribute = "xpath"_L1;
+constexpr auto virtualSlotAttribute = "virtual-slot"_L1;
+constexpr auto visibleAttribute = "visible"_L1;
+constexpr auto enumIdentifiedByValueAttribute = "identified-by-value"_L1;
+constexpr auto subModuleOfAttribute = "submodule-of"_L1;
+
+constexpr auto noAttributeValue = "no"_L1;
+constexpr auto yesAttributeValue = "yes"_L1;
+constexpr auto trueAttributeValue = "true"_L1;
+constexpr auto falseAttributeValue = "false"_L1;
static bool isTypeEntry(StackElement el)
{
@@ -135,7 +140,7 @@ static bool isDocumentation(StackElement el)
return el >= StackElement::FirstDocumentation && el <= StackElement::LastDocumentation;
}
-static QList<CustomConversion *> customConversionsForReview;
+static QList<CustomConversionPtr> customConversionsForReview;
// Set a regular expression for rejection from text. By legacy, those are fixed
// strings, except for '*' meaning 'match all'. Enclosing in "^..$"
@@ -148,7 +153,7 @@ static bool setRejectionRegularExpression(const QString &patternIn,
if (patternIn.startsWith(u'^') && patternIn.endsWith(u'$'))
pattern = patternIn;
else if (patternIn == u"*")
- pattern = QStringLiteral("^.*$");
+ pattern = "^.*$"_L1;
else
pattern = u'^' + QRegularExpression::escape(patternIn) + u'$';
re->setPattern(pattern);
@@ -159,15 +164,20 @@ static bool setRejectionRegularExpression(const QString &patternIn,
return true;
}
+static inline bool hasFileSnippetAttributes(const QXmlStreamAttributes *attributes)
+{
+ return attributes->hasAttribute(fileAttribute);
+}
+
// Extract a snippet from a file within annotation "// @snippet label".
std::optional<QString>
extractSnippet(const QString &code, const QString &snippetLabel)
{
if (snippetLabel.isEmpty())
return code;
- const QString pattern = QStringLiteral(R"(^\s*//\s*@snippet\s+)")
+ const QString pattern = R"(^\s*//\s*@snippet\s+)"_L1
+ QRegularExpression::escape(snippetLabel)
- + QStringLiteral(R"(\s*$)");
+ + R"(\s*$)"_L1;
const QRegularExpression snippetRe(pattern);
Q_ASSERT(snippetRe.isValid());
@@ -176,7 +186,7 @@ std::optional<QString>
QString result;
const auto lines = QStringView{code}.split(u'\n');
for (const auto &line : lines) {
- if (snippetRe.match(line).hasMatch()) {
+ if (snippetRe.matchView(line).hasMatch()) {
foundLabel = true;
useLine = !useLine;
if (!useLine)
@@ -189,48 +199,31 @@ std::optional<QString>
return CodeSnipAbstract::fixSpaces(result);
}
-template <class EnumType, Qt::CaseSensitivity cs = Qt::CaseInsensitive>
+template <class EnumType>
struct EnumLookup
{
QStringView name;
EnumType value;
};
-template <class EnumType, Qt::CaseSensitivity cs>
-bool operator==(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2)
-{
- return e1.name.compare(e2.name, cs) == 0;
-}
-
-template <class EnumType, Qt::CaseSensitivity cs>
-bool operator<(const EnumLookup<EnumType, cs> &e1, const EnumLookup<EnumType, cs> &e2)
-{
- return e1.name.compare(e2.name, cs) < 0;
-}
-
// Helper macros to define lookup functions that take a QStringView needle
// and an optional default return value.
#define ENUM_LOOKUP_BEGIN(EnumType, caseSensitivity, functionName) \
static std::optional<EnumType> functionName(QStringView needle) \
{ \
- using HaystackEntry = EnumLookup<EnumType, caseSensitivity>; \
- static const HaystackEntry haystack[] =
-
-#define ENUM_LOOKUP_LINEAR_SEARCH() \
- const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \
- const auto it = std::find(haystack, end, HaystackEntry{needle, {} }); \
+ using HaystackEntry = EnumLookup<EnumType>; \
+ constexpr auto cs = caseSensitivity; \
+ static constexpr HaystackEntry haystack[] =
+
+#define ENUM_LOOKUP_LINEAR_SEARCH \
+ auto pred = [cs, needle](const HaystackEntry &he) { \
+ return he.name.compare(needle, cs) == 0; \
+ }; \
+ auto end = std::cend(haystack); \
+ auto it = std::find_if(std::cbegin(haystack), end, pred); \
if (it != end) \
return it->value; \
- return {}; \
-}
-
-#define ENUM_LOOKUP_BINARY_SEARCH() \
- const auto end = haystack + sizeof(haystack) / sizeof(haystack[0]); \
- const HaystackEntry needleEntry{needle, {} }; \
- const auto lb = std::lower_bound(haystack, end, needleEntry); \
- if (lb != end && *lb == needleEntry) \
- return lb->value; \
- return {}; \
+ return std::nullopt; \
}
ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive,
@@ -242,7 +235,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::AllowThread, Qt::CaseInsensitive,
{u"no", TypeSystem::AllowThread::Disallow},
{u"false", TypeSystem::AllowThread::Disallow},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive,
@@ -253,7 +246,17 @@ ENUM_LOOKUP_BEGIN(TypeSystem::BoolCast, Qt::CaseInsensitive,
{u"no", TypeSystem::BoolCast::Disabled},
{u"false", TypeSystem::BoolCast::Disabled},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
+
+ENUM_LOOKUP_BEGIN(TypeSystem::PythonEnumType, Qt::CaseSensitive,
+ pythonEnumTypeFromAttribute)
+ {
+ {u"Enum", TypeSystem::PythonEnumType::Enum},
+ {u"IntEnum", TypeSystem::PythonEnumType::IntEnum},
+ {u"Flag", TypeSystem::PythonEnumType::Flag},
+ {u"IntFlag", TypeSystem::PythonEnumType::IntFlag},
+ };
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive,
qtMetaTypeFromAttribute)
@@ -264,7 +267,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::QtMetaTypeRegistration, Qt::CaseSensitive,
{u"no", TypeSystem::QtMetaTypeRegistration::Disabled},
{u"false", TypeSystem::QtMetaTypeRegistration::Disabled},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive,
languageFromAttribute)
@@ -274,7 +277,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Language, Qt::CaseInsensitive,
{u"shell", TypeSystem::ShellCode}, // coloca no header, mas antes da declaracao da classe
{u"target", TypeSystem::TargetLangCode} // em algum lugar do cpp
};
-ENUM_LOOKUP_BINARY_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive,
ownershipFromFromAttribute)
@@ -283,7 +286,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Ownership, Qt::CaseInsensitive,
{u"c++", TypeSystem::CppOwnership},
{u"default", TypeSystem::DefaultOwnership}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive,
addedFunctionAccessFromAttribute)
@@ -291,7 +294,7 @@ ENUM_LOOKUP_BEGIN(AddedFunction::Access, Qt::CaseInsensitive,
{u"public", AddedFunction::Public},
{u"protected", AddedFunction::Protected},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive,
modifierFromAttribute)
@@ -299,12 +302,11 @@ ENUM_LOOKUP_BEGIN(FunctionModification::ModifierFlag, Qt::CaseSensitive,
{u"private", FunctionModification::Private},
{u"public", FunctionModification::Public},
{u"protected", FunctionModification::Protected},
- {u"friendly", FunctionModification::Friendly},
{u"rename", FunctionModification::Rename},
{u"final", FunctionModification::Final},
{u"non-final", FunctionModification::NonFinal}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive,
referenceCountFromAttribute)
@@ -315,7 +317,7 @@ ENUM_LOOKUP_BEGIN(ReferenceCount::Action, Qt::CaseInsensitive,
{u"set", ReferenceCount::Set},
{u"ignore", ReferenceCount::Ignore}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive,
argumentOwnerActionFromAttribute)
@@ -323,16 +325,17 @@ ENUM_LOOKUP_BEGIN(ArgumentOwner::Action, Qt::CaseInsensitive,
{u"add", ArgumentOwner::Add},
{u"remove", ArgumentOwner::Remove}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::CodeSnipPosition, Qt::CaseInsensitive,
codeSnipPositionFromAttribute)
{
{u"beginning", TypeSystem::CodeSnipPositionBeginning},
{u"end", TypeSystem::CodeSnipPositionEnd},
- {u"declaration", TypeSystem::CodeSnipPositionDeclaration}
+ {u"declaration", TypeSystem::CodeSnipPositionDeclaration},
+ {u"override", TypeSystem::CodeSnipPositionPyOverride}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive,
locationFromAttribute)
@@ -341,7 +344,7 @@ ENUM_LOOKUP_BEGIN(Include::IncludeType, Qt::CaseInsensitive,
{u"local", Include::LocalPath},
{u"target", Include::TargetLangImport}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive,
docModificationFromAttribute)
@@ -350,7 +353,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::DocModificationMode, Qt::CaseInsensitive,
{u"prepend", TypeSystem::DocModificationPrepend},
{u"replace", TypeSystem::DocModificationReplace}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive,
containerTypeFromAttribute)
@@ -366,9 +369,10 @@ ENUM_LOOKUP_BEGIN(ContainerTypeEntry::ContainerKind, Qt::CaseSensitive,
{u"multi-map", ContainerTypeEntry::MultiMapContainer},
{u"hash", ContainerTypeEntry::MapContainer},
{u"multi-hash", ContainerTypeEntry::MultiMapContainer},
- {u"pair", ContainerTypeEntry::PairContainer}
+ {u"pair", ContainerTypeEntry::PairContainer},
+ {u"span", ContainerTypeEntry::SpanContainer}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive,
typeRejectionFromAttribute)
@@ -380,7 +384,7 @@ ENUM_LOOKUP_BEGIN(TypeRejection::MatchType, Qt::CaseSensitive,
{u"argument-type", TypeRejection::ArgumentType},
{u"return-type", TypeRejection::ReturnType}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive,
exceptionHandlingFromAttribute)
@@ -392,7 +396,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive,
{u"yes", TypeSystem::ExceptionHandling::On},
{u"true", TypeSystem::ExceptionHandling::On},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive,
smartPointerTypeFromAttribute)
@@ -402,7 +406,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SmartPointerType, Qt::CaseSensitive,
{u"value-handle", TypeSystem::SmartPointerType::ValueHandle},
{u"shared", TypeSystem::SmartPointerType::Shared}
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
template <class EnumType>
static std::optional<EnumType>
@@ -431,6 +435,7 @@ static const StackElementHash &stackElementHash()
{u"add-function", StackElement::AddFunction},
{u"add-pymethoddef", StackElement::AddPyMethodDef},
{u"array", StackElement::Array},
+ {u"configuration", StackElement::Configuration},
{u"container-type", StackElement::ContainerTypeEntry},
{u"conversion-rule", StackElement::ConversionRule},
{u"custom-constructor", StackElement::Unimplemented},
@@ -456,6 +461,7 @@ static const StackElementHash &stackElementHash()
{u"native-to-target", StackElement::NativeToTarget},
{u"no-null-pointer", StackElement::NoNullPointers},
{u"object-type", StackElement::ObjectTypeEntry},
+ {u"opaque-container", StackElement::OpaqueContainer},
{u"parent", StackElement::ParentOwner},
{u"primitive-type", StackElement::PrimitiveTypeEntry},
{u"property", StackElement::Property},
@@ -511,7 +517,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::SnakeCase, Qt::CaseSensitive,
{u"true", TypeSystem::SnakeCase::Enabled},
{u"both", TypeSystem::SnakeCase::Both},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive,
visibilityFromAttribute)
@@ -522,12 +528,12 @@ ENUM_LOOKUP_BEGIN(TypeSystem::Visibility, Qt::CaseSensitive,
{u"yes", TypeSystem::Visibility::Visible},
{u"true", TypeSystem::Visibility::Visible},
};
-ENUM_LOOKUP_LINEAR_SEARCH()
+ENUM_LOOKUP_LINEAR_SEARCH
static int indexOfAttribute(const QXmlStreamAttributes &atts,
- QStringView name)
+ QAnyStringView name)
{
- for (int i = 0, size = atts.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = atts.size(); i < size; ++i) {
if (atts.at(i).qualifiedName() == name)
return i;
}
@@ -558,7 +564,7 @@ static QString msgUnusedAttributes(QStringView tag, const QXmlStreamAttributes &
QString result;
QTextStream str(&result);
str << attributes.size() << " attributes(s) unused on <" << tag << ">: ";
- for (int i = 0, size = attributes.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = attributes.size(); i < size; ++i) {
if (i)
str << ", ";
str << attributes.at(i);
@@ -593,17 +599,17 @@ QString TypeSystemEntityResolver::readFile(const QString &entityName, QString *e
path = TypeDatabase::instance()->modifiedTypesystemFilepath(fileName, m_currentPath);
if (!QFileInfo::exists(path)) {
*errorMessage = u"Unable to resolve: "_s + entityName;
- return QString();
+ return {};
}
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
*errorMessage = msgCannotOpenForReading(file);
- return QString();
+ return {};
}
QString result = QString::fromUtf8(file.readAll()).trimmed();
// Remove license header comments on which QXmlStreamReader chokes
if (result.startsWith(u"<!--")) {
- const int commentEnd = result.indexOf(u"-->");
+ const auto commentEnd = result.indexOf(u"-->");
if (commentEnd != -1) {
result.remove(0, commentEnd + 3);
result = result.trimmed();
@@ -638,7 +644,7 @@ enum class ParserState
Template
};
-TypeSystemParser::TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context,
+TypeSystemParser::TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context,
bool generate) :
m_context(context),
m_generate(generate ? TypeEntry::GenerateCode : TypeEntry::GenerateForSubclass)
@@ -681,7 +687,7 @@ static QString msgReaderError(const ConditionalStreamReader &reader, const QStri
}
static QString msgUnimplementedElementWarning(const ConditionalStreamReader &reader,
- QStringView name)
+ QAnyStringView name)
{
QString message;
QTextStream(&message) << "The element \"" << name
@@ -706,7 +712,7 @@ static inline QString msgUnimplementedAttributeWarning(const ConditionalStreamRe
static QString
msgUnimplementedAttributeValueWarning(const ConditionalStreamReader &reader,
- QStringView name, QStringView value)
+ QAnyStringView name, QAnyStringView value)
{
QString message;
QTextStream(&message) << "The value \"" << value
@@ -723,21 +729,22 @@ static inline
attribute.value());
}
-static bool addRejection(TypeDatabase *database, QXmlStreamAttributes *attributes,
+static bool addRejection(TypeDatabase *database, bool generate, QXmlStreamAttributes *attributes,
QString *errorMessage)
{
- const int classIndex = indexOfAttribute(*attributes, classAttribute());
+ const auto classIndex = indexOfAttribute(*attributes, classAttribute);
if (classIndex == -1) {
- *errorMessage = msgMissingAttribute(classAttribute());
+ *errorMessage = msgMissingAttribute(classAttribute);
return false;
}
TypeRejection rejection;
+ rejection.generate = generate;
const QString className = attributes->takeAt(classIndex).value().toString();
if (!setRejectionRegularExpression(className, &rejection.className, errorMessage))
return false;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto &attribute = attributes->at(i);
const auto name = attribute.qualifiedName();
const auto typeOpt = typeRejectionFromAttribute(name);
@@ -864,13 +871,14 @@ bool TypeSystemParser::endElement(StackElement element)
if (m_generate == TypeEntry::GenerateCode) {
TypeDatabase::instance()->addGlobalUserFunctions(top->addedFunctions);
TypeDatabase::instance()->addGlobalUserFunctionModifications(top->functionMods);
- for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) {
- const CustomConversion::TargetToNativeConversions &toNatives = customConversion->targetToNativeConversions();
- for (CustomConversion::TargetToNativeConversion *toNative : toNatives)
- toNative->setSourceType(m_context->db->findType(toNative->sourceTypeName()));
+ for (const auto &customConversion : std::as_const(customConversionsForReview)) {
+ TargetToNativeConversions &toNatives =
+ customConversion->targetToNativeConversions();
+ for (auto &toNative : toNatives)
+ toNative.setSourceType(m_context->db->findType(toNative.sourceTypeName()));
}
}
- purgeEmptyCodeSnips(&top->entry->codeSnips());
+ purgeEmptyCodeSnips(&std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips());
break;
case StackElement::FunctionTypeEntry:
TypeDatabase::instance()->addGlobalUserFunctionModifications(top->functionMods);
@@ -882,7 +890,7 @@ bool TypeSystemParser::endElement(StackElement element)
case StackElement::NamespaceTypeEntry: {
Q_ASSERT(top->entry);
Q_ASSERT(top->entry->isComplex());
- auto *centry = static_cast<ComplexTypeEntry *>(top->entry);
+ auto centry = std::static_pointer_cast<ComplexTypeEntry>(top->entry);
purgeEmptyCodeSnips(&centry->codeSnips());
centry->setAddedFunctions(top->addedFunctions);
centry->setFunctionModifications(top->functionMods);
@@ -892,12 +900,15 @@ bool TypeSystemParser::endElement(StackElement element)
break;
case StackElement::TypedefTypeEntry: {
- auto *centry = static_cast<TypedefEntry *>(top->entry)->target();
+ auto centry = std::static_pointer_cast<TypedefEntry>(top->entry)->target();
centry->setAddedFunctions(centry->addedFunctions() + top->addedFunctions);
centry->setFunctionModifications(centry->functionModifications() + top->functionMods);
centry->setFieldModifications(centry->fieldModifications() + top->fieldMods);
- centry->setCodeSnips(centry->codeSnips() + top->entry->codeSnips());
centry->setDocModification(centry->docModifications() + top->docModifications);
+ if (top->entry->isComplex()) {
+ auto cte = std::static_pointer_cast<const ComplexTypeEntry>(top->entry);
+ centry->setCodeSnips(centry->codeSnips() + cte->codeSnips());
+ }
}
break;
@@ -909,29 +920,30 @@ bool TypeSystemParser::endElement(StackElement element)
Q_ASSERT(modIndex >= 0);
Q_ASSERT(!top->addedFunctions.isEmpty());
while (modIndex < top->functionMods.size())
- top->addedFunctions.last()->modifications.append(top->functionMods.takeAt(modIndex));
+ top->addedFunctions.last()->modifications().append(top->functionMods.takeAt(modIndex));
}
break;
case StackElement::NativeToTarget:
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."_s;
- return false;
- }
- customConversion->targetToNativeConversions().last()->setConversion(code);
- } else {
- customConversion->setNativeToTargetConversion(code);
+ case ParserState::PrimitiveTypeTargetToNativeConversion: {
+ auto customConversion = CustomConversion::getCustomConversion(top->entry);
+ if (!customConversion) {
+ m_error = msgMissingCustomConversion(top->entry);
+ return false;
+ }
+ QString code = top->conversionCodeSnips.constLast().code();
+ if (element == StackElement::AddConversion) {
+ if (customConversion->targetToNativeConversions().isEmpty()) {
+ m_error = u"CustomConversion's target to native conversions missing."_s;
+ return false;
}
+ customConversion->targetToNativeConversions().last().setConversion(code);
} else {
- m_error = u"CustomConversion object is missing."_s;
- return false;
+ customConversion->setNativeToTargetConversion(code);
}
+ }
break;
case ParserState::ArgumentNativeToTargetConversion: {
@@ -953,8 +965,6 @@ bool TypeSystemParser::endElement(StackElement element)
break;
case StackElement::EnumTypeEntry:
- top->entry->setDocModification(top->docModifications);
- top->docModifications = DocModificationList();
m_currentEnum = nullptr;
break;
case StackElement::Template:
@@ -1055,10 +1065,13 @@ CodeSnipAbstract *TypeSystemParser::injectCodeTarget(qsizetype offset) const
return &funcMod.snips().last();
}
case ParserState::TypeEntryCodeInjection:
+ Q_ASSERT(top->entry->isComplex());
+ return &std::static_pointer_cast<ComplexTypeEntry>(top->entry)->codeSnips().last();
case ParserState::TypeSystemCodeInjection:
- return &top->entry->codeSnips().last();
+ Q_ASSERT(top->entry->isTypeSystem());
+ return &std::static_pointer_cast<TypeSystemTypeEntry>(top->entry)->codeSnips().last();
case ParserState::Template:
- return m_templateEntry;
+ return m_templateEntry.get();
default:
break;
}
@@ -1092,15 +1105,22 @@ bool TypeSystemParser::characters(const String &ch)
return true;
}
- if (isDocumentation(type))
- m_contextStack.top()->docModifications.last().setCode(ch);
+ if (isDocumentation(type)) {
+ const bool isAddedFunction = m_stack.value(m_stack.size() - 2, StackElement::None)
+ == StackElement::AddFunction;
+ const auto &top = m_contextStack.top();
+ auto &docModifications = isAddedFunction
+ ? top->addedFunctions.last()->docModifications()
+ : top->docModifications;
+ docModifications.last().setCode(ch);
+ }
return true;
}
bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts)
{
- const QString fileName = atts.value(nameAttribute()).toString();
+ const QString fileName = atts.value(nameAttribute).toString();
if (fileName.isEmpty()) {
m_error = u"Required attribute 'name' missing for include-file tag."_s;
return false;
@@ -1115,11 +1135,11 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts)
}
}
- const auto quoteFrom = atts.value(quoteAfterLineAttribute());
+ const auto quoteFrom = atts.value(quoteAfterLineAttribute);
bool foundFromOk = quoteFrom.isEmpty();
bool from = quoteFrom.isEmpty();
- const auto quoteTo = atts.value(quoteBeforeLineAttribute());
+ const auto quoteTo = atts.value(quoteBeforeLineAttribute);
bool foundToOk = quoteTo.isEmpty();
bool to = true;
@@ -1139,10 +1159,10 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts)
}
}
if (!foundFromOk || !foundToOk) {
- QString fromError = QStringLiteral("Could not find quote-after-line='%1' in file '%2'.")
- .arg(quoteFrom.toString(), fileName);
- QString toError = QStringLiteral("Could not find quote-before-line='%1' in file '%2'.")
- .arg(quoteTo.toString(), fileName);
+ QString fromError = QString::fromLatin1("Could not find quote-after-line='%1' in file '%2'.")
+ .arg(quoteFrom.toString(), fileName);
+ QString toError = QString::fromLatin1("Could not find quote-before-line='%1' in file '%2'.")
+ .arg(quoteTo.toString(), fileName);
if (!foundToOk)
m_error = toError;
@@ -1156,29 +1176,27 @@ bool TypeSystemParser::importFileElement(const QXmlStreamAttributes &atts)
return true;
}
-static bool convertBoolean(QStringView value, const QString &attributeName, bool defaultValue)
+static bool convertBoolean(QStringView value, QAnyStringView attributeName, bool defaultValue)
{
- if (value.compare(trueAttributeValue(), Qt::CaseInsensitive) == 0
- || value.compare(yesAttributeValue(), Qt::CaseInsensitive) == 0) {
+ if (value.compare(trueAttributeValue, Qt::CaseInsensitive) == 0
+ || value.compare(yesAttributeValue, Qt::CaseInsensitive) == 0) {
return true;
}
- if (value.compare(falseAttributeValue(), Qt::CaseInsensitive) == 0
- || value.compare(noAttributeValue(), Qt::CaseInsensitive) == 0) {
+ if (value.compare(falseAttributeValue, Qt::CaseInsensitive) == 0
+ || value.compare(noAttributeValue, Qt::CaseInsensitive) == 0) {
return false;
}
- const QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.")
- .arg(value)
- .arg(attributeName,
- defaultValue ? yesAttributeValue() : noAttributeValue());
-
- qCWarning(lcShiboken).noquote().nospace() << warn;
+ qCWarning(lcShiboken).noquote().nospace() << "Boolean value '" << value
+ << "' not supported in attribute '" << attributeName
+ << "'. Use 'yes' or 'no'. Defaulting to '"
+ << (defaultValue ? yesAttributeValue : noAttributeValue) << "'.";
return defaultValue;
}
static bool convertRemovalAttribute(QStringView value)
{
return value == u"all" // Legacy
- || convertBoolean(value, removeAttribute(), false);
+ || convertBoolean(value, removeAttribute, false);
}
// Check whether an entry should be dropped, allowing for dropping the module
@@ -1188,7 +1206,7 @@ static bool shouldDropTypeEntry(const TypeDatabase *db,
QString name)
{
for (auto i = stack.size() - 1; i >= 0; --i) {
- if (auto *entry = stack.at(i)->entry) {
+ if (auto entry = stack.at(i)->entry) {
if (entry->type() == TypeEntry::TypeSystemType) {
if (db->shouldDropTypeEntry(name)) // Unqualified
return true;
@@ -1204,7 +1222,7 @@ static bool shouldDropTypeEntry(const TypeDatabase *db,
static QString checkSignatureError(const QString& signature, const QString& tag)
{
QString funcName = signature.left(signature.indexOf(u'(')).trimmed();
- static const QRegularExpression whiteSpace(QStringLiteral("\\s"));
+ static const QRegularExpression whiteSpace("\\s"_L1);
Q_ASSERT(whiteSpace.isValid());
if (!funcName.startsWith(u"operator ") && funcName.contains(whiteSpace)) {
return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n"
@@ -1215,7 +1233,7 @@ static QString checkSignatureError(const QString& signature, const QString& tag)
return QString();
}
-inline const TypeEntry *TypeSystemParser::currentParentTypeEntry() const
+inline TypeEntryCPtr TypeSystemParser::currentParentTypeEntry() const
{
const auto size = m_contextStack.size();
return size > 1 ? m_contextStack.at(size - 2)->entry : nullptr;
@@ -1224,7 +1242,7 @@ inline const TypeEntry *TypeSystemParser::currentParentTypeEntry() const
bool TypeSystemParser::checkRootElement()
{
for (auto i = m_contextStack.size() - 1; i >= 0; --i) {
- auto *e = m_contextStack.at(i)->entry;
+ auto e = m_contextStack.at(i)->entry;
if (e && e->isTypeSystem())
return true;
}
@@ -1232,7 +1250,7 @@ bool TypeSystemParser::checkRootElement()
return false;
}
-static TypeEntry *findViewedType(const QString &name)
+static TypeEntryPtr findViewedType(const QString &name)
{
const auto range = TypeDatabase::instance()->entries().equal_range(name);
for (auto i = range.first; i != range.second; ++i) {
@@ -1249,20 +1267,21 @@ static TypeEntry *findViewedType(const QString &name)
return nullptr;
}
-bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &reader, TypeEntry *type,
+bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &reader,
+ const TypeEntryPtr &type,
QXmlStreamAttributes *attributes)
{
type->setSourceLocation(SourceLocation(m_currentFile,
reader.lineNumber()));
type->setCodeGeneration(m_generate);
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"revision") {
type->setRevision(attributes->takeAt(i).value().toInt());
} else if (name == u"view-on") {
const QString name = attributes->takeAt(i).value().toString();
- TypeEntry *views = findViewedType(name);
- if (views == nullptr) {
+ TypeEntryPtr views = findViewedType(name);
+ if (!views) {
m_error = msgCannotFindView(name, type->name());
return false;
}
@@ -1272,55 +1291,55 @@ bool TypeSystemParser::applyCommonAttributes(const ConditionalStreamReader &read
return true;
}
-CustomTypeEntry *TypeSystemParser::parseCustomTypeEntry(const ConditionalStreamReader &,
+CustomTypeEntryPtr TypeSystemParser::parseCustomTypeEntry(const ConditionalStreamReader &,
const QString &name,
const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- auto *result = new CustomTypeEntry(name, since, m_contextStack.top()->entry);
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ auto result = std::make_shared<CustomTypeEntry>(name, since, m_contextStack.top()->entry);
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == checkFunctionAttribute())
+ if (name == checkFunctionAttribute)
result->setCheckFunction(attributes->takeAt(i).value().toString());
}
return result;
}
-FlagsTypeEntry *
+FlagsTypeEntryPtr
TypeSystemParser::parseFlagsEntry(const ConditionalStreamReader &reader,
- EnumTypeEntry *enumEntry, QString flagName,
+ const EnumTypeEntryPtr &enumEntry, QString flagName,
const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- auto ftype = new FlagsTypeEntry(u"QFlags<"_s + enumEntry->name() + u'>',
- since,
- currentParentTypeEntry()->typeSystemTypeEntry());
+ auto ftype = std::make_shared<FlagsTypeEntry>(u"QFlags<"_s + enumEntry->name() + u'>',
+ since,
+ typeSystemTypeEntry(currentParentTypeEntry()));
ftype->setOriginator(enumEntry);
ftype->setTargetLangPackage(enumEntry->targetLangPackage());
// Try toenumEntry get the guess the qualified flag name
- if (!flagName.contains(colonColon())) {
+ if (!flagName.contains(u"::"_s)) {
auto eq = enumEntry->qualifier();
if (!eq.isEmpty())
- flagName.prepend(eq + colonColon());
+ flagName.prepend(eq + u"::"_s);
}
ftype->setOriginalName(flagName);
if (!applyCommonAttributes(reader, ftype, attributes))
return nullptr;
- QStringList lst = flagName.split(colonColon());
+ QStringList lst = flagName.split(u"::"_s);
const QString name = lst.takeLast();
const QString targetLangFlagName = lst.join(u'.');
const QString &targetLangQualifier = enumEntry->targetLangQualifier();
if (targetLangFlagName != targetLangQualifier) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("enum %1 and flags %2 (%3) differ in qualifiers")
- .arg(targetLangQualifier, lst.value(0), targetLangFlagName);
+ qCWarning(lcShiboken, "enum %s and flags %s (%s) differ in qualifiers",
+ qPrintable(targetLangQualifier), qPrintable(lst.value(0)),
+ qPrintable(targetLangFlagName));
}
ftype->setFlagsName(name);
@@ -1337,7 +1356,7 @@ FlagsTypeEntry *
return ftype;
}
-SmartPointerTypeEntry *
+SmartPointerTypeEntryPtr
TypeSystemParser::parseSmartPointerEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
@@ -1351,7 +1370,7 @@ SmartPointerTypeEntry *
QString nullCheckMethod;
QString resetMethod;
QString instantiations;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"type") {
const auto attribute = attributes->takeAt(i);
@@ -1400,8 +1419,9 @@ SmartPointerTypeEntry *
return nullptr;
}
- auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType,
- refCountMethodName, since, currentParentTypeEntry());
+ auto type = std::make_shared<SmartPointerTypeEntry>(name, getter, smartPointerType,
+ refCountMethodName, since,
+ currentParentTypeEntry());
if (!applyCommonAttributes(reader, type, attributes))
return nullptr;
applyComplexTypeAttributes(reader, type, attributes);
@@ -1412,29 +1432,29 @@ SmartPointerTypeEntry *
return type;
}
-PrimitiveTypeEntry *
+PrimitiveTypeEntryPtr
TypeSystemParser::parsePrimitiveTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- auto *type = new PrimitiveTypeEntry(name, since, currentParentTypeEntry());
+ auto type = std::make_shared<PrimitiveTypeEntry>(name, since, currentParentTypeEntry());
QString targetLangApiName;
if (!applyCommonAttributes(reader, type, attributes))
return nullptr;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == targetLangNameAttribute()) {
+ if (name == targetLangNameAttribute) {
type->setTargetLangName(attributes->takeAt(i).value().toString());
} else if (name == u"target-lang-api-name") {
targetLangApiName = attributes->takeAt(i).value().toString();
- } else if (name == preferredConversionAttribute()) {
+ } else if (name == preferredConversionAttribute) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
- } else if (name == preferredTargetLangTypeAttribute()) {
+ } else if (name == preferredTargetLangTypeAttribute) {
const bool v = convertBoolean(attributes->takeAt(i).value(),
- preferredTargetLangTypeAttribute(), true);
+ preferredTargetLangTypeAttribute, true);
type->setPreferredTargetLangType(v);
} else if (name == u"default-constructor") {
type->setDefaultConstructor(attributes->takeAt(i).value().toString());
@@ -1442,40 +1462,53 @@ PrimitiveTypeEntry *
}
if (!targetLangApiName.isEmpty()) {
- auto *e = m_context->db->findType(targetLangApiName);
- if (e == nullptr || !e->isCustom()) {
+ auto e = m_context->db->findType(targetLangApiName);
+ if (!e || !e->isCustom()) {
m_error = msgInvalidTargetLanguageApiName(targetLangApiName);
return nullptr;
}
- type->setTargetLangApiType(static_cast<CustomTypeEntry *>(e));
+ type->setTargetLangApiType(std::static_pointer_cast<CustomTypeEntry>(e));
}
type->setTargetLangPackage(m_defaultPackage);
return type;
}
// "int:QList_int;QString:QList_QString"
-static bool parseOpaqueContainers(QStringView s, ContainerTypeEntry *cte)
+bool TypeSystemParser::parseOpaqueContainers(QStringView s, OpaqueContainers *result)
{
const auto entries = s.split(u';');
for (const auto &entry : entries) {
const auto values = entry.split(u':');
- if (values.size() != 2)
- return false;
- QString instantiation = values.at(0).trimmed().toString();
- QString name = values.at(1).trimmed().toString();
- cte->addOpaqueContainer({instantiation, name});
+ if (values.size() != 2) {
+ m_error = u"Error parsing the opaque container attribute: \""_s
+ + s.toString() + u"\"."_s;
+ return false;
+ }
+ OpaqueContainer oc;
+ oc.name = values.at(1).trimmed().toString();
+ const auto instantiations = values.at(0).split(u',', Qt::SkipEmptyParts);
+ for (const auto &instantiationV : instantiations) {
+ QString instantiation = instantiationV.trimmed().toString();
+ // Fix to match AbstractMetaType::signature() which is used for matching
+ // "Foo*" -> "Foo *"
+ const auto asteriskPos = instantiation.indexOf(u'*');
+ if (asteriskPos > 0 && !instantiation.at(asteriskPos - 1).isSpace())
+ instantiation.insert(asteriskPos, u' ');
+ oc.instantiations.append(instantiation);
+ }
+ result->append(oc);
}
return true;
}
-ContainerTypeEntry *
+ContainerTypeEntryPtr
TypeSystemParser::parseContainerTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- const int typeIndex = indexOfAttribute(*attributes, u"type");
+ const auto typeIndex = indexOfAttribute(*attributes, u"type");
if (typeIndex == -1) {
m_error = u"no 'type' attribute specified"_s;
return nullptr;
@@ -1487,40 +1520,61 @@ ContainerTypeEntry *
return nullptr;
}
attributes->removeAt(typeIndex);
- auto *type = new ContainerTypeEntry(name, containerTypeOpt.value(),
- since, currentParentTypeEntry());
+ auto type = std::make_shared<ContainerTypeEntry>(name, containerTypeOpt.value(),
+ since, currentParentTypeEntry());
if (!applyCommonAttributes(reader, type, attributes))
return nullptr;
applyComplexTypeAttributes(reader, type, attributes);
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == u"opaque-containers") {
+ if (name == opaqueContainerAttribute) {
const auto attribute = attributes->takeAt(i);
- if (!parseOpaqueContainers(attribute.value(), type)) {
- m_error = u"Error parsing the opaque container attribute: \""_s
- + attribute.value().toString() + u"\"."_s;
+ OpaqueContainers oc;
+ if (!parseOpaqueContainers(attribute.value(), &oc))
return nullptr;
- }
+ type->appendOpaqueContainers(oc);
}
}
return type;
}
-EnumTypeEntry *
+bool TypeSystemParser::parseOpaqueContainerElement(QXmlStreamAttributes *attributes)
+{
+ QString containerName;
+ OpaqueContainers oc;
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
+ const auto name = attributes->at(i).qualifiedName();
+ if (name == nameAttribute) {
+ containerName = attributes->takeAt(i).value().toString();
+ } else if (name == opaqueContainerAttribute) {
+ const auto attribute = attributes->takeAt(i);
+ if (!parseOpaqueContainers(attribute.value(), &oc))
+ return false;
+ }
+ }
+ if (containerName.isEmpty()) {
+ m_error = msgMissingAttribute(nameAttribute);
+ return false;
+ }
+ m_context->opaqueContainerHash[containerName].append(oc);
+ return true;
+}
+
+EnumTypeEntryPtr
TypeSystemParser::parseEnumTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- auto *entry = new EnumTypeEntry(name, since, currentParentTypeEntry());
+ auto entry = std::make_shared<EnumTypeEntry>(name, since, currentParentTypeEntry());
applyCommonAttributes(reader, entry, attributes);
entry->setTargetLangPackage(m_defaultPackage);
QString flagNames;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"upper-bound") {
qCWarning(lcShiboken, "%s",
@@ -1528,13 +1582,26 @@ EnumTypeEntry *
} else if (name == u"lower-bound") {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
- } else if (name == forceIntegerAttribute()) {
+ } else if (name == docFileAttribute) {
+ entry->setDocFile(attributes->takeAt(i).value().toString());
+ } else if (name == forceIntegerAttribute) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
- } else if (name == extensibleAttribute()) {
+ } else if (name == pythonEnumTypeAttribute) {
+ const auto attribute = attributes->takeAt(i);
+ const auto typeOpt = pythonEnumTypeFromAttribute(attribute.value());
+ if (typeOpt.has_value()) {
+ entry->setPythonEnumType(typeOpt.value());
+ } else {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgInvalidAttributeValue(attribute)));
+ }
+ } else if (name == cppEnumTypeAttribute) {
+ entry->setCppType(attributes->takeAt(i).value().toString());
+ } else if (name == extensibleAttribute) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
- } else if (name == flagsAttribute()) {
+ } else if (name == flagsAttribute) {
flagNames = attributes->takeAt(i).value().toString();
}
}
@@ -1549,17 +1616,17 @@ EnumTypeEntry *
}
-NamespaceTypeEntry *
+NamespaceTypeEntryPtr
TypeSystemParser::parseNamespaceTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- std::unique_ptr<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry()));
+ auto result = std::make_shared<NamespaceTypeEntry>(name, since, currentParentTypeEntry());
auto visibility = TypeSystem::Visibility::Unspecified;
- applyCommonAttributes(reader, result.get(), attributes);
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ applyCommonAttributes(reader, result, attributes);
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto attributeName = attributes->at(i).qualifiedName();
if (attributeName == u"files") {
const QString pattern = attributes->takeAt(i).value().toString();
@@ -1573,7 +1640,7 @@ NamespaceTypeEntry *
const auto extendsPackageName = attributes->at(i).value();
auto allEntries = TypeDatabase::instance()->findNamespaceTypes(name);
auto extendsIt = std::find_if(allEntries.cbegin(), allEntries.cend(),
- [extendsPackageName] (const NamespaceTypeEntry *e) {
+ [extendsPackageName] (const NamespaceTypeEntryCPtr &e) {
return e->targetLangPackage() == extendsPackageName;
});
if (extendsIt == allEntries.cend()) {
@@ -1582,7 +1649,7 @@ NamespaceTypeEntry *
}
result->setExtends(*extendsIt);
attributes->removeAt(i);
- } else if (attributeName == visibleAttribute()) {
+ } else if (attributeName == visibleAttribute) {
const auto attribute = attributes->takeAt(i);
const auto visibilityOpt = visibilityFromAttribute(attribute.value());
if (!visibilityOpt.has_value()) {
@@ -1590,35 +1657,36 @@ NamespaceTypeEntry *
return nullptr;
}
visibility = visibilityOpt.value();
- } else if (attributeName == generateAttribute()) {
- if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true))
+ } else if (attributeName == generateAttribute) {
+ if (!convertBoolean(attributes->takeAt(i).value(), generateAttribute, true))
visibility = TypeSystem::Visibility::Invisible;
- } else if (attributeName == generateUsingAttribute()) {
- result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(), generateUsingAttribute(), true));
+ } else if (attributeName == generateUsingAttribute) {
+ result->setGenerateUsing(convertBoolean(attributes->takeAt(i).value(),
+ generateUsingAttribute, true));
}
}
if (visibility != TypeSystem::Visibility::Unspecified)
result->setVisibility(visibility);
// Handle legacy "generate" before the common handling
- applyComplexTypeAttributes(reader, result.get(), attributes);
+ applyComplexTypeAttributes(reader, result, attributes);
if (result->extends() && !result->hasPattern()) {
m_error = msgExtendingNamespaceRequiresPattern(name);
- return nullptr;
+ return {};
}
- return result.release();
+ return result;
}
-ValueTypeEntry *
+ValueTypeEntryPtr
TypeSystemParser::parseValueTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
if (!checkRootElement())
return nullptr;
- auto *typeEntry = new ValueTypeEntry(name, since, currentParentTypeEntry());
+ auto typeEntry = std::make_shared<ValueTypeEntry>(name, since, currentParentTypeEntry());
if (!applyCommonAttributes(reader, typeEntry, attributes))
return nullptr;
applyComplexTypeAttributes(reader, typeEntry, attributes);
@@ -1629,7 +1697,7 @@ ValueTypeEntry *
return typeEntry;
}
-FunctionTypeEntry *
+FunctionTypeEntryPtr
TypeSystemParser::parseFunctionTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes)
@@ -1637,50 +1705,56 @@ FunctionTypeEntry *
if (!checkRootElement())
return nullptr;
- QString signature;
- TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Disabled;
+ FunctionModification mod;
+ const auto oldAttributesSize = attributes->size();
+ if (!parseModifyFunctionAttributes(attributes, &mod))
+ return nullptr;
+ const bool hasModification = attributes->size() < oldAttributesSize;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ QString originalSignature;
+ QString docFile;
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == signatureAttribute()) {
- signature = TypeDatabase::normalizedSignature(attributes->takeAt(i).value().toString());
- } else if (name == snakeCaseAttribute()) {
- const auto attribute = attributes->takeAt(i);
- const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
- if (!snakeCaseOpt.has_value()) {
- m_error = msgInvalidAttributeValue(attribute);
- return nullptr;
- }
- snakeCase = snakeCaseOpt.value();
- }
+ if (name == signatureAttribute)
+ originalSignature = attributes->takeAt(i).value().toString().simplified();
+ else if (name == docFileAttribute)
+ docFile = attributes->takeAt(i).value().toString();
}
+ const QString signature = TypeDatabase::normalizedSignature(originalSignature);
if (signature.isEmpty()) {
- m_error = msgMissingAttribute(signatureAttribute());
+ m_error = msgMissingAttribute(signatureAttribute);
return nullptr;
}
- TypeEntry *existingType = m_context->db->findType(name);
+ if (hasModification) {
+ mod.setOriginalSignature(originalSignature);
+ mod.setSignature(signature);
+ m_contextStack.top()->functionMods << mod;
+ }
+
+ TypeEntryPtr existingType = m_context->db->findType(name);
if (!existingType) {
- auto *result = new FunctionTypeEntry(name, signature, since, currentParentTypeEntry());
- result->setSnakeCase(snakeCase);
+ auto result = std::make_shared<FunctionTypeEntry>(name, signature, since,
+ currentParentTypeEntry());
+ result->setTargetLangPackage(m_defaultPackage);
+ result->setDocFile(docFile);
applyCommonAttributes(reader, result, attributes);
return result;
}
if (existingType->type() != TypeEntry::FunctionType) {
- m_error = QStringLiteral("%1 expected to be a function, but isn't! Maybe it was already declared as a class or something else.")
- .arg(name);
+ m_error = name + " expected to be a function, but isn't! Maybe it was already declared as a class or something else."_L1;
return nullptr;
}
- auto *result = reinterpret_cast<FunctionTypeEntry *>(existingType);
+ auto result = std::static_pointer_cast<FunctionTypeEntry>(existingType);
result->addSignature(signature);
return result;
}
-TypedefEntry *
+TypedefEntryPtr
TypeSystemParser::parseTypedefEntry(const ConditionalStreamReader &reader,
const QString &name, StackElement topElement,
const QVersionNumber &since,
@@ -1693,13 +1767,14 @@ TypedefEntry *
m_error = u"typedef entries must be nested in namespaces or type system."_s;
return nullptr;
}
- const int sourceIndex = indexOfAttribute(*attributes, sourceAttribute());
+ const auto sourceIndex = indexOfAttribute(*attributes, sourceAttribute);
if (sourceIndex == -1) {
- m_error = msgMissingAttribute(sourceAttribute());
+ m_error = msgMissingAttribute(sourceAttribute);
return nullptr;
}
const QString sourceType = attributes->takeAt(sourceIndex).value().toString();
- auto result = new TypedefEntry(name, sourceType, since, currentParentTypeEntry());
+ auto result = std::make_shared<TypedefEntry>(name, sourceType, since,
+ currentParentTypeEntry());
if (!applyCommonAttributes(reader, result, attributes))
return nullptr;
applyComplexTypeAttributes(reader, result, attributes);
@@ -1707,7 +1782,7 @@ TypedefEntry *
}
void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader &reader,
- ComplexTypeEntry *ctype,
+ const ComplexTypeEntryPtr &ctype,
QXmlStreamAttributes *attributes) const
{
bool generate = true;
@@ -1716,36 +1791,40 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
auto allowThread = m_allowThread;
QString package = m_defaultPackage;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == streamAttribute()) {
- ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute(), false));
- } else if (name == privateAttribute()) {
+ if (name == streamAttribute) {
+ ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute, false));
+ } else if (name == privateAttribute) {
ctype->setPrivate(convertBoolean(attributes->takeAt(i).value(),
- privateAttribute(), false));
- } else if (name == generateAttribute()) {
- generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true);
- } else if (name ==packageAttribute()) {
+ privateAttribute, false));
+ } else if (name == generateAttribute) {
+ generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true);
+ } else if (name ==packageAttribute) {
package = attributes->takeAt(i).value().toString();
- } else if (name == defaultSuperclassAttribute()) {
+ } else if (name == defaultSuperclassAttribute) {
ctype->setDefaultSuperclass(attributes->takeAt(i).value().toString());
- } else if (name == genericClassAttribute()) {
+ } else if (name == genericClassAttribute) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
- const bool v = convertBoolean(attributes->takeAt(i).value(), genericClassAttribute(), false);
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ genericClassAttribute, false);
ctype->setGenericClass(v);
- } else if (name == targetLangNameAttribute()) {
+ } else if (name == targetLangNameAttribute) {
ctype->setTargetLangName(attributes->takeAt(i).value().toString());
- } else if (name == u"polymorphic-base") {
- ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString());
+ } else if (name == polymorphicBaseAttribute) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ polymorphicBaseAttribute, false);
+ ctype->setIsPolymorphicBase(v);
} else if (name == u"polymorphic-name-function") {
ctype->setPolymorphicNameFunction(attributes->takeAt(i).value().toString());
} else if (name == u"polymorphic-id-expression") {
ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString());
- } else if (name == copyableAttribute()) {
- const bool v = convertBoolean(attributes->takeAt(i).value(), copyableAttribute(), false);
+ } else if (name == copyableAttribute) {
+ const bool v = convertBoolean(attributes->takeAt(i).value(),
+ copyableAttribute, false);
ctype->setCopyable(v ? ComplexTypeEntry::CopyableSet : ComplexTypeEntry::NonCopyableSet);
- } else if (name == exceptionHandlingAttribute()) {
+ } else if (name == exceptionHandlingAttribute) {
const auto attribute = attributes->takeAt(i);
const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value());
if (exceptionOpt.has_value()) {
@@ -1754,7 +1833,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == allowThreadAttribute()) {
+ } else if (name == allowThreadAttribute) {
const auto attribute = attributes->takeAt(i);
const auto allowThreadOpt = allowThreadFromAttribute(attribute.value());
if (allowThreadOpt.has_value()) {
@@ -1768,19 +1847,25 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
} else if (name == u"hash-function") {
ctype->setHashFunction(attributes->takeAt(i).value().toString());
- } else if (name == forceAbstractAttribute()) {
- if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute(), false))
+ } else if (name == forceAbstractAttribute) {
+ if (convertBoolean(attributes->takeAt(i).value(), forceAbstractAttribute, false))
ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract);
- } else if (name == deprecatedAttribute()) {
- if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute(), false))
+ } else if (name == deprecatedAttribute) {
+ if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute, false))
ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated);
- } else if (name == disableWrapperAttribute()) {
- if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute(), false))
+ } else if (name == disableWrapperAttribute) {
+ if (convertBoolean(attributes->takeAt(i).value(), disableWrapperAttribute, false))
ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DisableWrapper);
- } else if (name == deleteInMainThreadAttribute()) {
- if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false))
+ } else if (name == deleteInMainThreadAttribute) {
+ if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute, false))
ctype->setDeleteInMainThread(true);
- } else if (name == generateFunctionsAttribute()) {
+ } else if (name == qtMetaObjectFunctionsAttribute) {
+ if (!convertBoolean(attributes->takeAt(i).value(),
+ qtMetaObjectFunctionsAttribute, true)) {
+ ctype->setTypeFlags(ctype->typeFlags()
+ | ComplexTypeEntry::DisableQtMetaObjectFunctions);
+ }
+ } else if (name == generateFunctionsAttribute) {
const auto names = attributes->takeAt(i).value();
const auto nameList = names.split(u';', Qt::SkipEmptyParts);
QSet<QString> nameSet;
@@ -1789,7 +1874,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
ctype->setGenerateFunctions(nameSet);
} else if (name == u"target-type") {
ctype->setTargetType(attributes->takeAt(i).value().toString());
- } else if (name == snakeCaseAttribute()) {
+ } else if (name == snakeCaseAttribute) {
const auto attribute = attributes->takeAt(i);
const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
if (snakeCaseOpt.has_value()) {
@@ -1798,7 +1883,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == isNullAttribute()) {
+ } else if (name == isNullAttribute) {
const auto attribute = attributes->takeAt(i);
const auto boolCastOpt = boolCastFromAttribute(attribute.value());
if (boolCastOpt.has_value()) {
@@ -1807,7 +1892,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == operatorBoolAttribute()) {
+ } else if (name == operatorBoolAttribute) {
const auto attribute = attributes->takeAt(i);
const auto boolCastOpt = boolCastFromAttribute(attribute.value());
if (boolCastOpt.has_value()) {
@@ -1816,7 +1901,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == qtMetaTypeAttribute()) {
+ } else if (name == qtMetaTypeAttribute) {
const auto attribute = attributes->takeAt(i);
const auto qtMetaTypeOpt = qtMetaTypeFromAttribute(attribute.value());
if (qtMetaTypeOpt.has_value()) {
@@ -1825,9 +1910,9 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == parentManagementAttribute()) {
+ } else if (name == parentManagementAttribute) {
const auto attribute = attributes->takeAt(i);
- if (convertBoolean(attribute.value(), parentManagementAttribute(), false))
+ if (convertBoolean(attribute.value(), parentManagementAttribute, false))
ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ParentManagement);
ComplexTypeEntry::setParentManagementEnabled(true);
}
@@ -1848,23 +1933,49 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
ctype->setCodeGeneration(TypeEntry::GenerationDisabled);
}
+bool TypeSystemParser::parseConfiguration(StackElement topElement,
+ QXmlStreamAttributes *attributes)
+{
+ if (!isComplexTypeEntry(topElement)
+ && topElement != StackElement::EnumTypeEntry) {
+ m_error = u"<configuration> must be nested into a complex or enum type entry."_s;
+ return false;
+ }
+ QString condition;
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
+ const auto name = attributes->at(i).qualifiedName();
+ if (name == u"condition") {
+ condition = attributes->takeAt(i).value().toString();
+ }
+ }
+ if (condition.isEmpty()) {
+ m_error = u"<configuration> requires a \"condition\" attribute."_s;
+ return false;
+ }
+ const auto topEntry = m_contextStack.top()->entry;
+ const auto configurableEntry = std::dynamic_pointer_cast<ConfigurableTypeEntry>(topEntry);
+ Q_ASSERT(configurableEntry);
+ configurableEntry->setConfigCondition(condition);
+ return true;
+}
+
bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &,
QString *name, QXmlStreamAttributes *attributes)
{
QString signature;
QString rename;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == signatureAttribute()) {
+ if (name == signatureAttribute) {
// Do not remove as it is needed for the type entry later on
- signature = attributes->at(i).value().toString();
- } else if (name == renameAttribute()) {
+ signature = attributes->at(i).value().toString().simplified();
+ } else if (name == renameAttribute) {
rename = attributes->takeAt(i).value().toString();
}
}
if (signature.isEmpty()) {
- m_error = msgMissingAttribute(signatureAttribute());
+ m_error = msgMissingAttribute(signatureAttribute);
return false;
}
@@ -1897,10 +2008,11 @@ bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &,
bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *attributes)
{
+ const bool isAddFunction = topElement == StackElement::AddFunction;
const bool validParent = isTypeEntry(topElement)
|| topElement == StackElement::ModifyFunction
|| topElement == StackElement::ModifyField
- || topElement == StackElement::AddFunction;
+ || isAddFunction;
if (!validParent) {
m_error = u"inject-documentation must be inside modify-function, add-function"
"modify-field or other tags that creates a type"_s;
@@ -1909,7 +2021,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &,
TypeSystem::DocModificationMode mode = TypeSystem::DocModificationReplace;
TypeSystem::Language lang = TypeSystem::NativeCode;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"mode") {
const auto attribute = attributes->takeAt(i);
@@ -1919,7 +2031,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &,
return false;
}
mode = modeOpt.value();
- } else if (name == formatAttribute()) {
+ } else if (name == formatAttribute) {
const auto attribute = attributes->takeAt(i);
const auto langOpt = languageFromAttribute(attribute.value());
if (!langOpt.has_value()) {
@@ -1933,7 +2045,17 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &,
QString signature = isTypeEntry(topElement) ? QString() : m_currentSignature;
DocModification mod(mode, signature);
mod.setFormat(lang);
- m_contextStack.top()->docModifications << mod;
+ if (hasFileSnippetAttributes(attributes)) {
+ const auto snippetOptional = readFileSnippet(attributes);
+ if (!snippetOptional.has_value())
+ return false;
+ mod.setCode(snippetOptional.value().content);
+ }
+ auto &top = m_contextStack.top();
+ if (isAddFunction)
+ top->addedFunctions.last()->addDocModification(mod);
+ else
+ top->docModifications << mod;
return true;
}
@@ -1946,13 +2068,13 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &,
|| topElement == StackElement::ModifyField;
if (!validParent) {
m_error = u"modify-documentation must be inside modify-function, "
- "modify-field or other tags that creates a type"_qs;
+ "modify-field or other tags that creates a type"_s;
return false;
}
- const int xpathIndex = indexOfAttribute(*attributes, xPathAttribute());
+ const auto xpathIndex = indexOfAttribute(*attributes, xPathAttribute);
if (xpathIndex == -1) {
- m_error = msgMissingAttribute(xPathAttribute());
+ m_error = msgMissingAttribute(xPathAttribute);
return false;
}
@@ -1964,19 +2086,22 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &,
}
// m_exceptionHandling
-TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamReader &,
+TypeSystemTypeEntryPtr TypeSystemParser::parseRootElement(const ConditionalStreamReader &,
const QVersionNumber &since,
QXmlStreamAttributes *attributes)
{
TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified;
+ QString subModuleOf;
+ QString namespaceBegin;
+ QString namespaceEnd;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == packageAttribute()) {
+ if (name == packageAttribute) {
m_defaultPackage = attributes->takeAt(i).value().toString();
- } else if (name == defaultSuperclassAttribute()) {
+ } else if (name == defaultSuperclassAttribute) {
m_defaultSuperclass = attributes->takeAt(i).value().toString();
- } else if (name == exceptionHandlingAttribute()) {
+ } else if (name == exceptionHandlingAttribute) {
const auto attribute = attributes->takeAt(i);
const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value());
if (exceptionOpt.has_value()) {
@@ -1985,7 +2110,7 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == allowThreadAttribute()) {
+ } else if (name == allowThreadAttribute) {
const auto attribute = attributes->takeAt(i);
const auto allowThreadOpt = allowThreadFromAttribute(attribute.value());
if (allowThreadOpt.has_value()) {
@@ -1994,7 +2119,7 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
- } else if (name == snakeCaseAttribute()) {
+ } else if (name == snakeCaseAttribute) {
const auto attribute = attributes->takeAt(i);
const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
if (snakeCaseOpt.has_value()) {
@@ -2003,25 +2128,36 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const ConditionalStreamR
qCWarning(lcShiboken, "%s",
qPrintable(msgInvalidAttributeValue(attribute)));
}
+ } else if (name == subModuleOfAttribute) {
+ subModuleOf = attributes->takeAt(i).value().toString();
+ } else if (name == "namespace-begin"_L1) {
+ namespaceBegin = attributes->takeAt(i).value().toString();
+ } else if (name == "namespace-end"_L1) {
+ namespaceEnd = attributes->takeAt(i).value().toString();
}
}
if (m_defaultPackage.isEmpty()) { // Extending default, see addBuiltInContainerTypes()
- auto *moduleEntry = const_cast<TypeSystemTypeEntry *>(m_context->db->defaultTypeSystemType());
+ auto moduleEntry = std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->defaultTypeSystemType());
Q_ASSERT(moduleEntry);
m_defaultPackage = moduleEntry->name();
return moduleEntry;
}
- auto *moduleEntry =
- const_cast<TypeSystemTypeEntry *>(m_context->db->findTypeSystemType(m_defaultPackage));
- const bool add = moduleEntry == nullptr;
+ auto moduleEntry =
+ std::const_pointer_cast<TypeSystemTypeEntry>(m_context->db->findTypeSystemType(m_defaultPackage));
+ const bool add = !moduleEntry;
if (add) {
- moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since,
- currentParentTypeEntry());
+ moduleEntry.reset(new TypeSystemTypeEntry(m_defaultPackage, since,
+ currentParentTypeEntry()));
+ moduleEntry->setSubModule(subModuleOf);
}
moduleEntry->setCodeGeneration(m_generate);
moduleEntry->setSnakeCase(snakeCase);
+ if (!namespaceBegin.isEmpty())
+ moduleEntry->setNamespaceBegin(namespaceBegin);
+ if (!namespaceEnd.isEmpty())
+ moduleEntry->setNamespaceEnd(namespaceEnd);
if ((m_generate == TypeEntry::GenerateForSubclass ||
m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty())
@@ -2037,12 +2173,12 @@ bool TypeSystemParser::loadTypesystem(const ConditionalStreamReader &,
{
QString typeSystemName;
bool generateChild = true;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == nameAttribute())
+ if (name == nameAttribute)
typeSystemName = attributes->takeAt(i).value().toString();
- else if (name == generateAttribute())
- generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true);
+ else if (name == generateAttribute)
+ generateChild = convertBoolean(attributes->takeAt(i).value(), generateAttribute, true);
}
if (typeSystemName.isEmpty()) {
m_error = u"No typesystem name specified"_s;
@@ -2063,9 +2199,9 @@ bool TypeSystemParser::parseRejectEnumValue(const ConditionalStreamReader &,
m_error = u"<reject-enum-value> node must be used inside a <enum-type> node"_s;
return false;
}
- const int nameIndex = indexOfAttribute(*attributes, nameAttribute());
+ const auto nameIndex = indexOfAttribute(*attributes, nameAttribute);
if (nameIndex == -1) {
- m_error = msgMissingAttribute(nameAttribute());
+ m_error = msgMissingAttribute(nameAttribute);
return false;
}
m_currentEnum->addEnumValueRejection(attributes->takeAt(nameIndex).value().toString());
@@ -2080,7 +2216,7 @@ bool TypeSystemParser::parseReplaceArgumentType(const ConditionalStreamReader &,
m_error = u"Type replacement can only be specified for argument modifications"_s;
return false;
}
- const int modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute());
+ const auto modifiedTypeIndex = indexOfAttribute(*attributes, modifiedTypeAttribute);
if (modifiedTypeIndex == -1) {
m_error = u"Type replacement requires 'modified-type' attribute"_s;
return false;
@@ -2106,9 +2242,9 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
QString sourceFile;
QString snippetLabel;
TypeSystem::Language lang = TypeSystem::NativeCode;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == classAttribute()) {
+ if (name == classAttribute) {
const auto languageAttribute = attributes->takeAt(i);
const auto langOpt = languageFromAttribute(languageAttribute.value());
if (!langOpt.has_value()) {
@@ -2118,7 +2254,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
lang = langOpt.value();
} else if (name == u"file") {
sourceFile = attributes->takeAt(i).value().toString();
- } else if (name == snippetAttribute()) {
+ } else if (name == snippetAttribute) {
snippetLabel = attributes->takeAt(i).value().toString();
}
}
@@ -2131,14 +2267,18 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
return true;
}
- if (top->entry->hasTargetConversionRule() || top->entry->hasCustomConversion()) {
- m_error = u"Types can have only one conversion rule"_s;
- return false;
+ ValueTypeEntryPtr valueTypeEntry;
+ if (top->entry->isValue()) {
+ valueTypeEntry = std::static_pointer_cast<ValueTypeEntry>(top->entry);
+ if (valueTypeEntry->hasTargetConversionRule() || valueTypeEntry->hasCustomConversion()) {
+ m_error = u"Types can have only one conversion rule"_s;
+ return false;
+ }
}
// The old conversion rule tag that uses a file containing the conversion
// will be kept temporarily for compatibility reasons. FIXME PYSIDE7: Remove
- if (!sourceFile.isEmpty()) {
+ if (valueTypeEntry != nullptr && !sourceFile.isEmpty()) {
if (m_generate != TypeEntry::GenerateForSubclass
&& m_generate != TypeEntry::GenerateNothing) {
qWarning(lcShiboken, "Specifying conversion rules by \"file\" is deprecated.");
@@ -2156,12 +2296,18 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &,
m_error = msgCannotFindSnippet(sourceFile, snippetLabel);
return false;
}
- top->entry->setTargetConversionRule(conversionRuleOptional.value());
+ valueTypeEntry->setTargetConversionRule(conversionRuleOptional.value());
}
return true;
}
- auto *customConversion = new CustomConversion(top->entry);
+ auto customConversion = std::make_shared<CustomConversion>(top->entry);
+ if (top->entry->isPrimitive())
+ std::static_pointer_cast<PrimitiveTypeEntry>(top->entry)->setCustomConversion(customConversion);
+ else if (top->entry->isContainer())
+ std::static_pointer_cast<ContainerTypeEntry>(top->entry)->setCustomConversion(customConversion);
+ else if (top->entry->isValue())
+ std::static_pointer_cast<ValueTypeEntry>(top->entry)->setCustomConversion(customConversion);
customConversionsForReview.append(customConversion);
return true;
}
@@ -2175,7 +2321,7 @@ bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &,
return false;
}
CodeSnip snip;
- if (!readFileSnippet(attributes, &snip))
+ if (!readCodeSnippet(attributes, &snip))
return false;
m_contextStack.top()->conversionCodeSnips.append(snip);
return true;
@@ -2192,7 +2338,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &,
QString sourceTypeName;
QString typeCheck;
CodeSnip snip;
- if (!readFileSnippet(attributes, &snip))
+ if (!readCodeSnippet(attributes, &snip))
return false;
const auto &top = m_contextStack.top();
@@ -2201,7 +2347,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &,
if (parserState() == ParserState::ArgumentTargetToNativeConversion)
return true;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"type")
sourceTypeName = attributes->takeAt(i).value().toString();
@@ -2213,7 +2359,12 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &,
m_error = u"Target to Native conversions must specify the input type with the 'type' attribute."_s;
return false;
}
- top->entry->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck);
+ auto customConversion = CustomConversion::getCustomConversion(top->entry);
+ if (!customConversion) {
+ m_error = msgMissingCustomConversion(top->entry);
+ return false;
+ }
+ customConversion->addTargetToNativeConversion(sourceTypeName, typeCheck);
return true;
}
@@ -2222,7 +2373,7 @@ static bool parseIndex(const QString &index, int *result, QString *errorMessage)
bool ok = false;
*result = index.toInt(&ok);
if (!ok)
- *errorMessage = QStringLiteral("Cannot convert '%1' to integer").arg(index);
+ *errorMessage = QString::fromLatin1("Cannot convert '%1' to integer").arg(index);
return ok;
}
@@ -2255,22 +2406,22 @@ bool TypeSystemParser::parseModifyArgument(const ConditionalStreamReader &,
QString renameTo;
QString pyiType;
bool resetAfterUse = false;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == indexAttribute()) {
+ if (name == indexAttribute) {
index = attributes->takeAt(i).value().toString();
- } else if (name == invalidateAfterUseAttribute()) {
+ } else if (name == invalidateAfterUseAttribute) {
resetAfterUse = convertBoolean(attributes->takeAt(i).value(),
- invalidateAfterUseAttribute(), false);
- } else if (name == renameAttribute()) {
+ invalidateAfterUseAttribute, false);
+ } else if (name == renameAttribute) {
renameTo = attributes->takeAt(i).value().toString();
- } else if (name == pyiTypeAttribute()) {
+ } else if (name == pyiTypeAttribute) {
pyiType = attributes->takeAt(i).value().toString();
}
}
if (index.isEmpty()) {
- m_error = msgMissingAttribute(indexAttribute());
+ m_error = msgMissingAttribute(indexAttribute);
return false;
}
@@ -2318,9 +2469,9 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &,
TypeSystem::Language lang = TypeSystem::TargetLangCode;
std::optional<TypeSystem::Ownership> ownershipOpt;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == classAttribute()) {
+ if (name == classAttribute) {
const auto classAttribute = attributes->takeAt(i);
const auto langOpt = languageFromAttribute(classAttribute.value());
if (!langOpt.has_value() || langOpt.value() == TypeSystem::ShellCode) {
@@ -2328,7 +2479,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &,
return false;
}
lang = langOpt.value();
- } else if (name == ownershipAttribute()) {
+ } else if (name == ownershipAttribute) {
const auto attribute = attributes->takeAt(i);
ownershipOpt = ownershipFromFromAttribute(attribute.value());
if (!ownershipOpt.has_value()) {
@@ -2339,7 +2490,7 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &,
}
if (!ownershipOpt.has_value()) {
- m_error = QStringLiteral("unspecified ownership");
+ m_error = "unspecified ownership"_L1;
return false;
}
auto &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods().last();
@@ -2366,9 +2517,9 @@ bool TypeSystemParser::parseRename(const ConditionalStreamReader &,
return false;
}
- const int toIndex = indexOfAttribute(*attributes, toAttribute());
+ const auto toIndex = indexOfAttribute(*attributes, toAttribute);
if (toIndex == -1) {
- m_error = msgMissingAttribute(toAttribute());
+ m_error = msgMissingAttribute(toAttribute);
return false;
}
const QString renamed_to = attributes->takeAt(toIndex).value().toString();
@@ -2380,22 +2531,22 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &,
QXmlStreamAttributes *attributes)
{
FieldModification fm;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == nameAttribute()) {
+ if (name == nameAttribute) {
fm.setName(attributes->takeAt(i).value().toString());
- } else if (name == removeAttribute()) {
+ } else if (name == removeAttribute) {
fm.setRemoved(convertRemovalAttribute(attributes->takeAt(i).value()));
- } else if (name == opaqueContainerFieldAttribute()) {
+ } else if (name == opaqueContainerFieldAttribute) {
fm.setOpaqueContainer(convertBoolean(attributes->takeAt(i).value(),
- opaqueContainerFieldAttribute(), false));
- } else if (name == readAttribute()) {
- fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute(), true));
- } else if (name == writeAttribute()) {
- fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute(), true));
- } else if (name == renameAttribute()) {
+ opaqueContainerFieldAttribute, false));
+ } else if (name == readAttribute) {
+ fm.setReadable(convertBoolean(attributes->takeAt(i).value(), readAttribute, true));
+ } else if (name == writeAttribute) {
+ fm.setWritable(convertBoolean(attributes->takeAt(i).value(), writeAttribute, true));
+ } else if (name == renameAttribute) {
fm.setRenamedToName(attributes->takeAt(i).value().toString());
- } else if (name == snakeCaseAttribute()) {
+ } else if (name == snakeCaseAttribute) {
const auto attribute = attributes->takeAt(i);
const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
if (snakeCaseOpt.has_value()) {
@@ -2407,7 +2558,7 @@ bool TypeSystemParser::parseModifyField(const ConditionalStreamReader &,
}
}
if (fm.name().isEmpty()) {
- m_error = msgMissingAttribute(nameAttribute());
+ m_error = msgMissingAttribute(nameAttribute);
return false;
}
m_contextStack.top()->fieldMods << fm;
@@ -2439,29 +2590,37 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &,
", was=%1").arg(tagFromElement(topElement));
return false;
}
+
+ FunctionModification mod;
+ if (!(t == StackElement::AddFunction
+ ? parseBasicModifyFunctionAttributes(attributes, &mod)
+ : parseModifyFunctionAttributes(attributes, &mod))) {
+ return false;
+ }
+
QString originalSignature;
QString returnType;
bool staticFunction = false;
bool classMethod = false;
+ bool pythonOverride = false;
QString access;
- int overloadNumber = TypeSystem::OverloadNumberUnset;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == u"signature") {
- originalSignature = attributes->takeAt(i).value().toString();
+ if (name == signatureAttribute) {
+ originalSignature = attributes->takeAt(i).value().toString().simplified();
} else if (name == u"return-type") {
returnType = attributes->takeAt(i).value().toString();
- } else if (name == staticAttribute()) {
+ } else if (name == staticAttribute) {
staticFunction = convertBoolean(attributes->takeAt(i).value(),
- staticAttribute(), false);
- } else if (name == classmethodAttribute()) {
+ staticAttribute, false);
+ } else if (name == classmethodAttribute) {
classMethod = convertBoolean(attributes->takeAt(i).value(),
- classmethodAttribute(), false);
- } else if (name == accessAttribute()) {
+ classmethodAttribute, false);
+ } else if (name == accessAttribute) {
access = attributes->takeAt(i).value().toString();
- } else if (name == overloadNumberAttribute()) {
- if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error))
- return false;
+ } else if (name == pythonOverrideAttribute) {
+ pythonOverride = convertBoolean(attributes->takeAt(i).value(),
+ pythonOverrideAttribute, false);
}
}
@@ -2478,13 +2637,15 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &,
}
AddedFunctionPtr func = AddedFunction::createAddedFunction(signature, returnType, &errorString);
- if (func.isNull()) {
+ if (!func) {
m_error = errorString;
return false;
}
func->setStatic(staticFunction);
func->setClassMethod(classMethod);
+ func->setPythonOverride(pythonOverride);
+ func->setTargetLangPackage(m_defaultPackage);
// Create signature for matching modifications
signature = TypeDatabase::normalizedSignature(originalSignature);
@@ -2506,8 +2667,6 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &,
m_contextStack.top()->addedFunctionModificationIndex =
m_contextStack.top()->functionMods.size();
- FunctionModification mod;
- mod.setOverloadNumber(overloadNumber);
if (!mod.setSignature(m_currentSignature, &m_error))
return false;
mod.setOriginalSignature(originalSignature);
@@ -2526,9 +2685,9 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &,
}
TypeSystemPyMethodDefEntry def;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == nameAttribute()) {
+ if (name == nameAttribute) {
def.name = attributes->takeAt(i).value().toString();
} else if (name == u"doc") {
def.doc = attributes->takeAt(i).value().toString();
@@ -2551,7 +2710,7 @@ bool TypeSystemParser::parseAddPyMethodDef(const ConditionalStreamReader &,
m_error = u"add-pymethoddef requires at least a name and a function attribute"_s;
return false;
}
- static_cast<ComplexTypeEntry *>(m_contextStack.top()->entry)->addPyMethodDef(def);
+ std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addPyMethodDef(def);
return true;
}
@@ -2565,9 +2724,9 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme
}
TypeSystemProperty property;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == nameAttribute()) {
+ if (name == nameAttribute) {
property.name = attributes->takeAt(i).value().toString();
} else if (name == u"get") {
property.read = attributes->takeAt(i).value().toString();
@@ -2575,17 +2734,78 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackEleme
property.type = attributes->takeAt(i).value().toString();
} else if (name == u"set") {
property.write = attributes->takeAt(i).value().toString();
- } else if (name == generateGetSetDefAttribute()) {
+ } else if (name == generateGetSetDefAttribute) {
property.generateGetSetDef =
convertBoolean(attributes->takeAt(i).value(),
- generateGetSetDefAttribute(), false);
+ generateGetSetDefAttribute, false);
}
}
if (!property.isValid()) {
m_error = u"<property> element is missing required attibutes (name/type/get)."_s;
return false;
}
- static_cast<ComplexTypeEntry *>(m_contextStack.top()->entry)->addProperty(property);
+ std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addProperty(property);
+ return true;
+}
+
+// Parse basic attributes applicable to <add-function>/<declare-function>/<function>
+// and <modify-function> (all that is not done by injected code).
+bool TypeSystemParser::parseBasicModifyFunctionAttributes(QXmlStreamAttributes *attributes,
+ FunctionModification *mod)
+{
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
+ const auto name = attributes->at(i).qualifiedName();
+ if (name == overloadNumberAttribute) {
+ int overloadNumber = TypeSystem::OverloadNumberUnset;
+ if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error))
+ return false;
+ mod->setOverloadNumber(overloadNumber);
+ }
+ }
+ return true;
+}
+
+// Parse attributes applicable to <declare-function>/<function>
+// and <modify-function>.
+bool TypeSystemParser::parseModifyFunctionAttributes(QXmlStreamAttributes *attributes,
+ FunctionModification *mod)
+{
+ if (!parseBasicModifyFunctionAttributes(attributes, mod))
+ return false;
+
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
+ const auto name = attributes->at(i).qualifiedName();
+ if (name == allowThreadAttribute) {
+ const QXmlStreamAttribute attribute = attributes->takeAt(i);
+ const auto allowThreadOpt = allowThreadFromAttribute(attribute.value());
+ if (!allowThreadOpt.has_value()) {
+ m_error = msgInvalidAttributeValue(attribute);
+ return false;
+ }
+ mod->setAllowThread(allowThreadOpt.value());
+ } else if (name == exceptionHandlingAttribute) {
+ const auto attribute = attributes->takeAt(i);
+ const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value());
+ if (!exceptionOpt.has_value()) {
+ m_error = msgInvalidAttributeValue(attribute);
+ return false;
+ }
+ mod->setExceptionHandling(exceptionOpt.value());
+ } else if (name == snakeCaseAttribute) {
+ const auto attribute = attributes->takeAt(i);
+ const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
+ if (!snakeCaseOpt.has_value()) {
+ m_error = msgInvalidAttributeValue(attribute);
+ return false;
+ }
+ mod->setSnakeCase(snakeCaseOpt.value());
+ } else if (name == deprecatedAttribute) {
+ const bool deprecated = convertBoolean(attributes->takeAt(i).value(),
+ deprecatedAttribute, false);
+ mod->setModifierFlag(deprecated ? FunctionModification::Deprecated
+ : FunctionModification::Undeprecated);
+ }
+ }
return true;
}
@@ -2603,61 +2823,24 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader
}
QString originalSignature;
+ FunctionModification mod;
+ if (!parseModifyFunctionAttributes(attributes, &mod))
+ return false;
+
QString access;
bool removed = false;
QString rename;
- bool deprecated = false;
- bool isThread = false;
- int overloadNumber = TypeSystem::OverloadNumberUnset;
- TypeSystem::ExceptionHandling exceptionHandling = TypeSystem::ExceptionHandling::Unspecified;
- TypeSystem::AllowThread allowThread = TypeSystem::AllowThread::Unspecified;
- TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == u"signature") {
- originalSignature = attributes->takeAt(i).value().toString();
- } else if (name == accessAttribute()) {
+ if (name == signatureAttribute) {
+ originalSignature = attributes->takeAt(i).value().toString().simplified();
+ } else if (name == accessAttribute) {
access = attributes->takeAt(i).value().toString();
- } else if (name == renameAttribute()) {
+ } else if (name == renameAttribute) {
rename = attributes->takeAt(i).value().toString();
- } else if (name == removeAttribute()) {
+ } else if (name == removeAttribute) {
removed = convertRemovalAttribute(attributes->takeAt(i).value());
- } else if (name == deprecatedAttribute()) {
- deprecated = convertBoolean(attributes->takeAt(i).value(),
- deprecatedAttribute(), false);
- } else if (name == threadAttribute()) {
- isThread = convertBoolean(attributes->takeAt(i).value(),
- threadAttribute(), false);
- } else if (name == allowThreadAttribute()) {
- const QXmlStreamAttribute attribute = attributes->takeAt(i);
- const auto allowThreadOpt = allowThreadFromAttribute(attribute.value());
- if (!allowThreadOpt.has_value()) {
- m_error = msgInvalidAttributeValue(attribute);
- return false;
- }
- allowThread = allowThreadOpt.value();
- } else if (name == exceptionHandlingAttribute()) {
- const auto attribute = attributes->takeAt(i);
- const auto exceptionOpt = exceptionHandlingFromAttribute(attribute.value());
- if (exceptionOpt.has_value()) {
- exceptionHandling = exceptionOpt.value();
- } else {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgInvalidAttributeValue(attribute)));
- }
- } else if (name == overloadNumberAttribute()) {
- if (!parseOverloadNumber(attributes->takeAt(i), &overloadNumber, &m_error))
- return false;
- } else if (name == snakeCaseAttribute()) {
- const auto attribute = attributes->takeAt(i);
- const auto snakeCaseOpt = snakeCaseFromAttribute(attribute.value());
- if (snakeCaseOpt.has_value()) {
- snakeCase = snakeCaseOpt.value();
- } else {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgInvalidAttributeValue(attribute)));
- }
- } else if (name == virtualSlotAttribute()) {
+ } else if (name == virtualSlotAttribute || name == threadAttribute) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeWarning(reader, name)));
}
@@ -2666,7 +2849,7 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader
// Child of global <function>
const auto &top = m_contextStack.top();
if (originalSignature.isEmpty() && top->entry->isFunction()) {
- auto f = static_cast<const FunctionTypeEntry *>(top->entry);
+ auto f = std::static_pointer_cast<const FunctionTypeEntry>(top->entry);
originalSignature = f->signatures().value(0);
}
@@ -2682,13 +2865,9 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader
return false;
}
- FunctionModification mod;
if (!mod.setSignature(signature, &m_error))
return false;
mod.setOriginalSignature(originalSignature);
- mod.setExceptionHandling(exceptionHandling);
- mod.setOverloadNumber(overloadNumber);
- mod.setSnakeCase(snakeCase);
m_currentSignature = signature;
if (!access.isEmpty()) {
@@ -2698,17 +2877,14 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader
return false;
}
const FunctionModification::ModifierFlag m = modifierFlagOpt.value();
- if (m == FunctionModification::Final || m == FunctionModification::NonFinal) {
+ if (m == FunctionModification::NonFinal) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnimplementedAttributeValueWarning(reader,
- accessAttribute(), access)));
+ accessAttribute, access)));
}
mod.setModifierFlag(m);
}
- if (deprecated)
- mod.setModifierFlag(FunctionModification::Deprecated);
-
mod.setRemoved(removed);
if (!rename.isEmpty()) {
@@ -2716,10 +2892,6 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader
mod.setModifierFlag(FunctionModification::Rename);
}
- mod.setIsThread(isThread);
- if (allowThread != TypeSystem::AllowThread::Unspecified)
- mod.setAllowThread(allowThread);
-
top->functionMods << mod;
return true;
}
@@ -2732,7 +2904,7 @@ bool TypeSystemParser::parseReplaceDefaultExpression(const ConditionalStreamRead
m_error = u"Replace default expression only allowed as child of argument modification"_s;
return false;
}
- const int withIndex = indexOfAttribute(*attributes, u"with");
+ const auto withIndex = indexOfAttribute(*attributes, u"with");
if (withIndex == -1 || attributes->at(withIndex).value().isEmpty()) {
m_error = u"Default expression replaced with empty string. Use remove-default-expression instead."_s;
return false;
@@ -2753,9 +2925,9 @@ bool TypeSystemParser::parseReferenceCount(const ConditionalStreamReader &reader
}
ReferenceCount rc;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == actionAttribute()) {
+ if (name == actionAttribute) {
const QXmlStreamAttribute attribute = attributes->takeAt(i);
const auto actionOpt = referenceCountFromAttribute(attribute.value());
if (!actionOpt.has_value()) {
@@ -2790,13 +2962,13 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &,
return false;
}
ArgumentOwner ao;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == indexAttribute()) {
+ if (name == indexAttribute) {
const QString index = attributes->takeAt(i).value().toString();
if (!parseArgumentIndex(index, &ao.index, &m_error))
return false;
- } else if (name == actionAttribute()) {
+ } else if (name == actionAttribute) {
const auto action = attributes->takeAt(i);
const auto actionOpt = argumentOwnerActionFromAttribute(action.value());
if (!actionOpt.has_value()) {
@@ -2810,46 +2982,62 @@ bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &,
return true;
}
-bool TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip)
+std::optional<TypeSystemParser::Snippet>
+ TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes)
{
- QString fileName;
- QString snippetLabel;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ Snippet result;
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == u"file") {
- fileName = attributes->takeAt(i).value().toString();
- } else if (name == snippetAttribute()) {
- snippetLabel = attributes->takeAt(i).value().toString();
+ if (name == fileAttribute) {
+ result.fileName = attributes->takeAt(i).value().toString();
+ } else if (name == snippetAttribute) {
+ result.snippetLabel = attributes->takeAt(i).value().toString();
}
}
- if (fileName.isEmpty())
- return true;
- const QString resolved = m_context->db->modifiedTypesystemFilepath(fileName, m_currentPath);
+ if (result.fileName.isEmpty()) {
+ m_error = "Snippet missing file name"_L1;
+ return std::nullopt;
+ }
+ const QString resolved = m_context->db->modifiedTypesystemFilepath(result.fileName,
+ m_currentPath);
if (!QFile::exists(resolved)) {
m_error = u"File for inject code not exist: "_s
- + QDir::toNativeSeparators(fileName);
- return false;
+ + QDir::toNativeSeparators(result.fileName);
+ return std::nullopt;
}
QFile codeFile(resolved);
if (!codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) {
m_error = msgCannotOpenForReading(codeFile);
- return false;
+ return std::nullopt;
}
- const auto codeOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()), snippetLabel);
+ const auto contentOptional = extractSnippet(QString::fromUtf8(codeFile.readAll()),
+ result.snippetLabel);
codeFile.close();
- if (!codeOptional.has_value()) {
- m_error = msgCannotFindSnippet(resolved, snippetLabel);
- return false;
+ if (!contentOptional.has_value()) {
+ m_error = msgCannotFindSnippet(resolved, result.snippetLabel);
+ return std::nullopt;
}
+ result.content = contentOptional.value();
+ return result;
+}
+
+bool TypeSystemParser::readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip)
+{
+ if (!hasFileSnippetAttributes(attributes))
+ return true; // Expecting inline content.
+ const auto snippetOptional = readFileSnippet(attributes);
+ if (!snippetOptional.has_value())
+ return false;
+ const auto snippet = snippetOptional.value();
- QString source = fileName;
- if (!snippetLabel.isEmpty())
- source += u" ("_s + snippetLabel + u')';
+ QString source = snippet.fileName;
+ if (!snippet.snippetLabel.isEmpty())
+ source += " ("_L1 + snippet.snippetLabel + u')';
QString content;
QTextStream str(&content);
str << "// ========================================================================\n"
"// START of custom code block [file: "
- << source << "]\n" << codeOptional.value()
+ << source << "]\n" << snippet.content
<< "// END of custom code block [file: " << source
<< "]\n// ========================================================================\n";
snip->addCode(content);
@@ -2871,11 +3059,11 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &,
TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionBeginning;
TypeSystem::Language lang = TypeSystem::TargetLangCode;
CodeSnip snip;
- if (!readFileSnippet(attributes, &snip))
+ if (!readCodeSnippet(attributes, &snip))
return false;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == classAttribute()) {
+ if (name == classAttribute) {
const auto attribute = attributes->takeAt(i);
const auto langOpt = languageFromAttribute(attribute.value());
if (!langOpt.has_value()) {
@@ -2883,7 +3071,7 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &,
return false;
}
lang = langOpt.value();
- } else if (name == positionAttribute()) {
+ } else if (name == positionAttribute) {
const auto attribute = attributes->takeAt(i);
const auto positionOpt = codeSnipPositionFromAttribute(attribute.value());
if (!positionOpt.has_value()) {
@@ -2897,29 +3085,36 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &,
snip.position = position;
snip.language = lang;
- if (topElement == StackElement::ModifyFunction
- || topElement == StackElement::AddFunction) {
+ switch (topElement) {
+ case StackElement::ModifyFunction:
+ case StackElement::AddFunction: {
FunctionModification &mod = m_contextStack.top()->functionMods.last();
mod.appendSnip(snip);
if (!snip.code().isEmpty())
mod.setModifierFlag(FunctionModification::CodeInjection);
- } else {
- m_contextStack.top()->entry->addCodeSnip(snip);
+ }
+ break;
+ case StackElement::Root:
+ std::static_pointer_cast<TypeSystemTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip);
+ break;
+ default:
+ std::static_pointer_cast<ComplexTypeEntry>(m_contextStack.top()->entry)->addCodeSnip(snip);
+ break;
}
return true;
}
bool TypeSystemParser::parseInclude(const ConditionalStreamReader &,
StackElement topElement,
- TypeEntry *entry, QXmlStreamAttributes *attributes)
+ const TypeEntryPtr &entry, QXmlStreamAttributes *attributes)
{
QString fileName;
Include::IncludeType location = Include::IncludePath;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
- if (name == fileNameAttribute()) {
+ if (name == fileNameAttribute) {
fileName = attributes->takeAt(i).value().toString();
- } else if (name == locationAttribute()) {
+ } else if (name == locationAttribute) {
const auto attribute = attributes->takeAt(i);
const auto locationOpt = locationFromAttribute(attribute.value());
if (!locationOpt.has_value()) {
@@ -2949,12 +3144,12 @@ bool TypeSystemParser::parseInclude(const ConditionalStreamReader &,
bool TypeSystemParser::parseSystemInclude(const ConditionalStreamReader &,
QXmlStreamAttributes *attributes)
{
- const int index = indexOfAttribute(*attributes, fileNameAttribute());
+ const auto index = indexOfAttribute(*attributes, fileNameAttribute);
if (index == -1) {
- m_error = msgMissingAttribute(fileNameAttribute());
+ m_error = msgMissingAttribute(fileNameAttribute);
return false;
}
- TypeDatabase::instance()->addSystemInclude(attributes->takeAt(index).value().toString());
+ TypeDatabase::instance()->addForceProcessSystemInclude(attributes->takeAt(index).value().toString());
return true;
}
@@ -2972,9 +3167,9 @@ TemplateInstance *
"conversion-rule, native-to-target or add-conversion tags."_s;
return nullptr;
}
- const int nameIndex = indexOfAttribute(*attributes, nameAttribute());
+ const auto nameIndex = indexOfAttribute(*attributes, nameAttribute);
if (nameIndex == -1) {
- m_error = msgMissingAttribute(nameAttribute());
+ m_error = msgMissingAttribute(nameAttribute);
return nullptr;
}
return new TemplateInstance(attributes->takeAt(nameIndex).value().toString());
@@ -2989,11 +3184,11 @@ bool TypeSystemParser::parseReplace(const ConditionalStreamReader &,
}
QString from;
QString to;
- for (int i = attributes->size() - 1; i >= 0; --i) {
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
const auto name = attributes->at(i).qualifiedName();
if (name == u"from")
from = attributes->takeAt(i).value().toString();
- else if (name == toAttribute())
+ else if (name == toAttribute)
to = attributes->takeAt(i).value().toString();
}
m_templateInstance->addReplaceRule(from, to);
@@ -3010,7 +3205,7 @@ bool TypeSystemParser::checkDuplicatedTypeEntry(const ConditionalStreamReader &r
{
if (t == StackElement::PrimitiveTypeEntry || t == StackElement::FunctionTypeEntry)
return true;
- const auto *duplicated = m_context->db->findType(name);
+ const auto duplicated = m_context->db->findType(name);
if (!duplicated || duplicated->isNamespace())
return true;
if (duplicated->isBuiltIn()) {
@@ -3047,14 +3242,14 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
QXmlStreamAttributes attributes = reader.attributes();
VersionRange versionRange;
- for (int i = attributes.size() - 1; i >= 0; --i) {
+ for (auto i = attributes.size() - 1; i >= 0; --i) {
const auto name = attributes.at(i).qualifiedName();
- if (name == sinceAttribute()) {
+ if (name == sinceAttribute) {
if (!parseVersion(attributes.takeAt(i).value().toString(),
m_defaultPackage, &versionRange.since, &m_error)) {
return false;
}
- } else if (name == untilAttribute()) {
+ } else if (name == untilAttribute) {
if (!parseVersion(attributes.takeAt(i).value().toString(),
m_defaultPackage, &versionRange.until, &m_error)) {
return false;
@@ -3063,7 +3258,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
}
if (!m_defaultPackage.isEmpty() && !versionRange.isNull()) {
- TypeDatabase* td = TypeDatabase::instance();
+ auto *td = TypeDatabase::instance();
if (!td->checkApiVersion(m_defaultPackage, versionRange)) {
++m_ignoreDepth;
return true;
@@ -3088,7 +3283,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
}
if (isTypeEntry(element) || element == StackElement::Root)
- m_contextStack.push(StackElementContextPtr(new StackElementContext()));
+ m_contextStack.push(std::make_shared<StackElementContext>());
if (m_contextStack.isEmpty()) {
m_error = msgNoRootTypeSystemEntry();
@@ -3101,11 +3296,11 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
if (isTypeEntry(element)) {
QString name;
if (element != StackElement::FunctionTypeEntry) {
- const int nameIndex = indexOfAttribute(attributes, nameAttribute());
+ const auto nameIndex = indexOfAttribute(attributes, nameAttribute);
if (nameIndex != -1) {
name = attributes.takeAt(nameIndex).value().toString();
} else if (element != StackElement::EnumTypeEntry) { // anonymous enum?
- m_error = msgMissingAttribute(nameAttribute());
+ m_error = msgMissingAttribute(nameAttribute);
return false;
}
}
@@ -3118,7 +3313,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
if (m_context->db->hasDroppedTypeEntries()) {
const QString identifier = element == StackElement::FunctionTypeEntry
- ? attributes.value(signatureAttribute()).toString() : name;
+ ? attributes.value(signatureAttribute).toString().simplified() : name;
if (shouldDropTypeEntry(m_context->db, m_contextStack, identifier)) {
m_currentDroppedEntryDepth = 1;
if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
@@ -3142,14 +3337,15 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
// types (which we need to do in order to support fake meta objects)
if (element != StackElement::PrimitiveTypeEntry
&& element != StackElement::FunctionTypeEntry) {
- TypeEntry *tmp = m_context->db->findType(name);
+ TypeEntryPtr tmp = m_context->db->findType(name);
if (tmp && !tmp->isNamespace())
qCWarning(lcShiboken).noquote().nospace()
<< "Duplicate type entry: '" << name << '\'';
}
if (element == StackElement::EnumTypeEntry) {
- const int enumIdentifiedByIndex = indexOfAttribute(attributes, enumIdentifiedByValueAttribute());
+ const auto enumIdentifiedByIndex =
+ indexOfAttribute(attributes, enumIdentifiedByValueAttribute);
const QString identifiedByValue = enumIdentifiedByIndex != -1
? attributes.takeAt(enumIdentifiedByIndex).value().toString() : QString();
if (name.isEmpty()) {
@@ -3208,7 +3404,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
case StackElement::InterfaceTypeEntry: {
if (!checkRootElement())
return false;
- auto *ce = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry());
+ auto ce = std::make_shared<ObjectTypeEntry>(name, versionRange.since, currentParentTypeEntry());
top->entry = ce;
applyCommonAttributes(reader, top->entry, &attributes);
applyComplexTypeAttributes(reader, ce, &attributes);
@@ -3256,7 +3452,8 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
|| element == StackElement::ConversionRule
|| element == StackElement::AddFunction
|| element == StackElement::DeclareFunction
- || element == StackElement::Template;
+ || element == StackElement::Template
+ || element == StackElement::OpaqueContainer;
if (!topLevel && m_stack.at(m_stack.size() - 2) == StackElement::Root) {
m_error = u"Tag requires parent: '"_s + tagName.toString() + u'\'';
@@ -3295,11 +3492,16 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
const auto topParent = m_stack.value(m_stack.size() - 3, StackElement::None);
if (isTypeEntry(topParent)) {
- const int replaceIndex = indexOfAttribute(attributes, replaceAttribute());
+ const auto replaceIndex = indexOfAttribute(attributes, replaceAttribute);
const bool replace = replaceIndex == -1
|| convertBoolean(attributes.takeAt(replaceIndex).value(),
- replaceAttribute(), true);
- top->entry->customConversion()->setReplaceOriginalTargetToNativeConversions(replace);
+ replaceAttribute, true);
+ auto customConversion = CustomConversion::getCustomConversion(top->entry);
+ if (!customConversion) {
+ m_error = msgMissingCustomConversion(top->entry);
+ return false;
+ }
+ customConversion->setReplaceOriginalTargetToNativeConversions(replace);
}
}
break;
@@ -3320,14 +3522,17 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
return false;
break;
case StackElement::SuppressedWarning: {
- const int textIndex = indexOfAttribute(attributes, textAttribute());
+ const auto textIndex = indexOfAttribute(attributes, textAttribute);
if (textIndex == -1) {
qCWarning(lcShiboken) << "Suppressed warning with no text specified";
} else {
const QString suppressedWarning =
attributes.takeAt(textIndex).value().toString();
- if (!m_context->db->addSuppressedWarning(suppressedWarning, &m_error))
+ if (!m_context->db->addSuppressedWarning(suppressedWarning,
+ m_generate == TypeEntry::GenerateCode,
+ &m_error)) {
return false;
+ }
}
}
break;
@@ -3396,32 +3601,39 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
return false;
break;
case StackElement::Rejection:
- if (!addRejection(m_context->db, &attributes, &m_error))
+ if (!addRejection(m_context->db, m_generate == TypeEntry::GenerateCode,
+ &attributes, &m_error)) {
return false;
+ }
break;
case StackElement::SystemInclude:
if (!parseSystemInclude(reader, &attributes))
return false;
break;
case StackElement::Template: {
- const int nameIndex = indexOfAttribute(attributes, nameAttribute());
+ const auto nameIndex = indexOfAttribute(attributes, nameAttribute);
if (nameIndex == -1) {
- m_error = msgMissingAttribute(nameAttribute());
+ m_error = msgMissingAttribute(nameAttribute);
return false;
}
- m_templateEntry =
- new TemplateEntry(attributes.takeAt(nameIndex).value().toString());
+ m_templateEntry.reset(new TemplateEntry(attributes.takeAt(nameIndex).value().toString()));
}
break;
case StackElement::InsertTemplate:
m_templateInstance.reset(parseInsertTemplate(reader, topElement, &attributes));
- if (m_templateInstance.isNull())
+ if (!m_templateInstance)
return false;
break;
case StackElement::Replace:
if (!parseReplace(reader, topElement, &attributes))
return false;
break;
+ case StackElement::OpaqueContainer:
+ if (!parseOpaqueContainerElement(&attributes))
+ case StackElement::Configuration:
+ if (!parseConfiguration(topElement, &attributes))
+ return false;
+ break;
default:
break; // nada
}
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser_p.h b/sources/shiboken6/ApiExtractor/typesystemparser_p.h
index c14a46c04..4d9d4fd92 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser_p.h
+++ b/sources/shiboken6/ApiExtractor/typesystemparser_p.h
@@ -4,14 +4,18 @@
#define TYPESYSTEMPARSER_H
#include "typesystem.h"
+#include "containertypeentry.h"
#include "typedatabase.h"
#include "typedatabase_p.h"
+#include "typesystem_typedefs.h"
#include "codesnip.h"
#include <QtCore/QStack>
#include <QtCore/QHash>
#include <QtCore/QScopedPointer>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
+#include <optional>
QT_FORWARD_DECLARE_CLASS(QVersionNumber)
QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes)
@@ -100,6 +104,8 @@ enum class StackElement {
ArgumentModifiers,
ImportFile,
+ OpaqueContainer,
+ Configuration,
Unimplemented
};
@@ -120,19 +126,19 @@ struct StackElementContext
FunctionModificationList functionMods;
FieldModificationList fieldMods;
DocModificationList docModifications;
- TypeEntry* entry = nullptr;
+ TypeEntryPtr entry;
int addedFunctionModificationIndex = -1;
};
class TypeSystemParser
{
public:
- Q_DISABLE_COPY(TypeSystemParser)
+ Q_DISABLE_COPY_MOVE(TypeSystemParser)
- using StackElementContextPtr = QSharedPointer<StackElementContext>;
+ using StackElementContextPtr = std::shared_ptr<StackElementContext>;
using ContextStack = QStack<StackElementContextPtr>;
- explicit TypeSystemParser(const QSharedPointer<TypeDatabaseParserContext> &context,
+ explicit TypeSystemParser(const std::shared_ptr<TypeDatabaseParserContext> &context,
bool generate);
~TypeSystemParser();
@@ -141,10 +147,17 @@ public:
QString errorString() const { return m_error; }
private:
+ struct Snippet
+ {
+ QString content;
+ QString fileName;
+ QString snippetLabel;
+ };
+
bool parseXml(ConditionalStreamReader &reader);
bool setupSmartPointerInstantiations();
bool startElement(const ConditionalStreamReader &reader, StackElement element);
- SmartPointerTypeEntry *parseSmartPointerEntry(const ConditionalStreamReader &,
+ SmartPointerTypeEntryPtr parseSmartPointerEntry(const ConditionalStreamReader &,
const QString &name,
const QVersionNumber &since,
QXmlStreamAttributes *attributes);
@@ -154,51 +167,56 @@ private:
bool importFileElement(const QXmlStreamAttributes &atts);
- const TypeEntry *currentParentTypeEntry() const;
+ TypeEntryCPtr currentParentTypeEntry() const;
bool checkRootElement();
- bool applyCommonAttributes(const ConditionalStreamReader &reader, TypeEntry *type,
+ bool applyCommonAttributes(const ConditionalStreamReader &reader,
+ const TypeEntryPtr &type,
QXmlStreamAttributes *attributes);
- PrimitiveTypeEntry *
+ PrimitiveTypeEntryPtr
parsePrimitiveTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- CustomTypeEntry *
+ CustomTypeEntryPtr
parseCustomTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- ContainerTypeEntry *
+ bool parseOpaqueContainers(QStringView s, OpaqueContainers *result);
+ ContainerTypeEntryPtr
parseContainerTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- EnumTypeEntry *
+ bool parseOpaqueContainerElement(QXmlStreamAttributes *attributes);
+ EnumTypeEntryPtr
parseEnumTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- FlagsTypeEntry *
- parseFlagsEntry(const ConditionalStreamReader &, EnumTypeEntry *enumEntry,
+ FlagsTypeEntryPtr
+ parseFlagsEntry(const ConditionalStreamReader &, const EnumTypeEntryPtr &enumEntry,
QString flagName, const QVersionNumber &since,
QXmlStreamAttributes *);
- NamespaceTypeEntry *
+ NamespaceTypeEntryPtr
parseNamespaceTypeEntry(const ConditionalStreamReader &,
const QString &name, const QVersionNumber &since,
QXmlStreamAttributes *attributes);
- ValueTypeEntry *
+ ValueTypeEntryPtr
parseValueTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- FunctionTypeEntry *
+ FunctionTypeEntryPtr
parseFunctionTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
- TypedefEntry *
+ TypedefEntryPtr
parseTypedefEntry(const ConditionalStreamReader &, const QString &name,
StackElement topElement,
const QVersionNumber &since, QXmlStreamAttributes *);
- void applyComplexTypeAttributes(const ConditionalStreamReader &, ComplexTypeEntry *ctype,
+ void applyComplexTypeAttributes(const ConditionalStreamReader &, const ComplexTypeEntryPtr &ctype,
QXmlStreamAttributes *) const;
+ bool parseConfiguration(StackElement topElement,
+ QXmlStreamAttributes *attributes);
bool parseRenameFunction(const ConditionalStreamReader &, QString *name,
QXmlStreamAttributes *);
bool parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *);
bool parseModifyDocumentation(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *);
- TypeSystemTypeEntry *
+ TypeSystemTypeEntryPtr
parseRootElement(const ConditionalStreamReader &, const QVersionNumber &since,
QXmlStreamAttributes *);
bool loadTypesystem(const ConditionalStreamReader &, QXmlStreamAttributes *);
@@ -226,6 +244,10 @@ private:
StackElement topElement, QXmlStreamAttributes *attributes);
bool parseProperty(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *);
+ bool parseBasicModifyFunctionAttributes(QXmlStreamAttributes *,
+ FunctionModification *mod);
+ bool parseModifyFunctionAttributes(QXmlStreamAttributes *,
+ FunctionModification *mod);
bool parseModifyFunction(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *);
bool parseReplaceDefaultExpression(const ConditionalStreamReader &,
@@ -234,10 +256,11 @@ private:
QXmlStreamAttributes *);
bool parseParentOwner(const ConditionalStreamReader &, StackElement topElement,
QXmlStreamAttributes *);
- bool readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip);
+ std::optional<Snippet> readFileSnippet(QXmlStreamAttributes *attributes);
+ bool readCodeSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip);
bool parseInjectCode(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *);
bool parseInclude(const ConditionalStreamReader &, StackElement topElement,
- TypeEntry *entry, QXmlStreamAttributes *);
+ const TypeEntryPtr &entry, QXmlStreamAttributes *);
bool parseSystemInclude(const ConditionalStreamReader &, QXmlStreamAttributes *);
TemplateInstance
*parseInsertTemplate(const ConditionalStreamReader &, StackElement topElement,
@@ -249,7 +272,7 @@ private:
ParserState parserState(qsizetype offset = 0) const;
CodeSnipAbstract *injectCodeTarget(qsizetype offset = 0) const;
- QSharedPointer<TypeDatabaseParserContext> m_context;
+ std::shared_ptr<TypeDatabaseParserContext> m_context;
QStack<StackElement> m_stack;
int m_currentDroppedEntryDepth = 0;
int m_ignoreDepth = 0;
@@ -260,9 +283,9 @@ private:
QString m_error;
const TypeEntry::CodeGeneration m_generate;
- EnumTypeEntry* m_currentEnum = nullptr;
+ EnumTypeEntryPtr m_currentEnum;
TemplateInstancePtr m_templateInstance;
- TemplateEntry *m_templateEntry = nullptr;
+ TemplateEntryPtr m_templateEntry;
ContextStack m_contextStack;
QString m_currentSignature;
diff --git a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h
index 87d1101d3..9b9670696 100644
--- a/sources/shiboken6/ApiExtractor/typesystemtypeentry.h
+++ b/sources/shiboken6/ApiExtractor/typesystemtypeentry.h
@@ -5,18 +5,34 @@
#define TYPESYSTEMTYPEENTRY_H
#include "typesystem.h"
+#include "modifications_typedefs.h"
+#include "typesystem_enums.h"
+#include "typesystem_typedefs.h"
class TypeSystemTypeEntry : public TypeEntry
{
public:
explicit TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
TypeEntry *clone() const override;
TypeSystem::SnakeCase snakeCase() const;
void setSnakeCase(TypeSystem::SnakeCase sc);
+ const CodeSnipList &codeSnips() const;
+ CodeSnipList &codeSnips();
+ void addCodeSnip(const CodeSnip &codeSnip);
+
+ QString subModuleOf() const;
+ void setSubModule(const QString &);
+
+ const QString &namespaceBegin() const;
+ void setNamespaceBegin(const QString &n);
+
+ const QString &namespaceEnd() const;
+ void setNamespaceEnd(const QString &n);
+
protected:
explicit TypeSystemTypeEntry(TypeEntryPrivate *d);
};
diff --git a/sources/shiboken6/ApiExtractor/usingmember.h b/sources/shiboken6/ApiExtractor/usingmember.h
index d908da0cd..346eab13c 100644
--- a/sources/shiboken6/ApiExtractor/usingmember.h
+++ b/sources/shiboken6/ApiExtractor/usingmember.h
@@ -5,14 +5,14 @@
#define USINGMEMBER_H
#include "abstractmetalang_typedefs.h"
-#include "parser/codemodel.h"
+#include "parser/codemodel_enums.h"
QT_FORWARD_DECLARE_CLASS(QDebug)
struct UsingMember // Introducing a base class member via 'using' directive
{
QString memberName;
- const AbstractMetaClass *baseClass;
+ AbstractMetaClassCPtr baseClass;
Access access;
};
diff --git a/sources/shiboken6/ApiExtractor/valuetypeentry.h b/sources/shiboken6/ApiExtractor/valuetypeentry.h
index 15cac1a79..97bc26803 100644
--- a/sources/shiboken6/ApiExtractor/valuetypeentry.h
+++ b/sources/shiboken6/ApiExtractor/valuetypeentry.h
@@ -5,12 +5,27 @@
#define VALUETYPEENTRY_H
#include "complextypeentry.h"
+#include "customconversion_typedefs.h"
class ValueTypeEntry : public ComplexTypeEntry
{
public:
explicit ValueTypeEntry(const QString &entryName, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
+
+ bool hasCustomConversion() const;
+ void setCustomConversion(const CustomConversionPtr &customConversion);
+ CustomConversionPtr customConversion() const;
+
+ // FIXME PYSIDE7: Remove
+ /// Set the target type conversion rule
+ void setTargetConversionRule(const QString &conversionRule);
+
+ /// Returns the target type conversion rule
+ QString targetConversionRule() const;
+
+ /// TODO-CONVERTER: mark as deprecated
+ bool hasTargetConversionRule() const;
bool isValue() const override;
@@ -18,7 +33,7 @@ public:
protected:
explicit ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr,
- const TypeEntry *parent);
+ const TypeEntryCPtr &parent);
explicit ValueTypeEntry(ComplexTypeEntryPrivate *d);
};
diff --git a/sources/shiboken6/ApiExtractor/xmlutils.cpp b/sources/shiboken6/ApiExtractor/xmlutils.cpp
index b0c9c2084..ccacd4ce7 100644
--- a/sources/shiboken6/ApiExtractor/xmlutils.cpp
+++ b/sources/shiboken6/ApiExtractor/xmlutils.cpp
@@ -21,13 +21,13 @@ QString XQuery::evaluate(QString xPathExpression, QString *errorMessage)
return doEvaluate(xPathExpression, errorMessage);
}
-QSharedPointer<XQuery> XQuery::create(const QString &focus, QString *errorMessage)
+std::shared_ptr<XQuery> XQuery::create(const QString &focus, QString *errorMessage)
{
#if defined(HAVE_LIBXSLT)
return libXml_createXQuery(focus, errorMessage);
#else
*errorMessage = QLatin1StringView(__FUNCTION__) + u" is not implemented."_s;
- return QSharedPointer<XQuery>();
+ return std::shared_ptr<XQuery>();
#endif
}
diff --git a/sources/shiboken6/ApiExtractor/xmlutils.h b/sources/shiboken6/ApiExtractor/xmlutils.h
index 2d6adbe9e..ac23c9c9c 100644
--- a/sources/shiboken6/ApiExtractor/xmlutils.h
+++ b/sources/shiboken6/ApiExtractor/xmlutils.h
@@ -3,19 +3,20 @@
#ifndef XMLUTILS_H
#define XMLUTILS_H
-#include <QtCore/QSharedPointer>
#include <QtCore/QString>
+#include <memory>
+
class XQuery
{
public:
- Q_DISABLE_COPY(XQuery);
+ Q_DISABLE_COPY_MOVE(XQuery)
virtual ~XQuery();
QString evaluate(QString xPathExpression, QString *errorMessage);
- static QSharedPointer<XQuery> create(const QString &focus, QString *errorMessage);
+ static std::shared_ptr<XQuery> create(const QString &focus, QString *errorMessage);
protected:
XQuery();
diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp
index fad8889fa..5a9a26913 100644
--- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp
+++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.cpp
@@ -40,8 +40,6 @@ static void ensureInitialized()
}
}
-namespace {
-
// RAI Helpers for cleaning up libxml2/libxslt data
struct XmlDocDeleter // for std::unique_ptr<xmlDoc>
@@ -64,8 +62,6 @@ struct XmlXPathContextDeleter
void operator()(xmlXPathContextPtr xPathContext) { xmlXPathFreeContext(xPathContext); }
};
-} // namespace
-
using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>;
using XmlPathObjectUniquePtr = std::unique_ptr<xmlXPathObject, XmlXPathObjectDeleter>;
using XmlStyleSheetUniquePtr = std::unique_ptr<xsltStylesheet, XmlStyleSheetDeleter>;
@@ -141,9 +137,10 @@ QString LibXmlXQuery::doEvaluate(const QString &xPathExpression, QString *errorM
return result;
}
-QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage)
+std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage)
{
- XmlDocUniquePtr doc(xmlParseFile(QFile::encodeName(focus).constData()));
+ XmlDocUniquePtr doc(xmlReadFile(QFile::encodeName(focus).constData(),
+ "utf-8", XML_PARSE_NOENT));
if (!doc) {
*errorMessage = u"libxml2: Cannot set focus to "_s + QDir::toNativeSeparators(focus);
return {};
@@ -153,25 +150,27 @@ QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorM
*errorMessage = u"libxml2: xmlXPathNewContext() failed"_s;
return {};
}
- return QSharedPointer<XQuery>(new LibXmlXQuery(doc, xpathContext));
+ return std::shared_ptr<XQuery>(new LibXmlXQuery(doc, xpathContext));
}
// XSLT transformation
-static const char xsltPrefix[] = R"(<?xml version="1.0" encoding="UTF-8" ?>
+static constexpr auto xsltPrefix = R"(<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-)";
+)"_L1;
QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage)
{
ensureInitialized();
// Read XML data
if (!xsl.startsWith(u"<?xml")) {
- xsl.prepend(QLatin1StringView(xsltPrefix));
+ xsl.prepend(xsltPrefix);
xsl.append(u"</xsl:transform>"_s);
}
const QByteArray xmlData = xml.toUtf8();
- XmlDocUniquePtr xmlDoc(xmlParseMemory(xmlData.constData(), xmlData.size()));
+
+ XmlDocUniquePtr xmlDoc(xmlReadMemory(xmlData.constData(), int(xmlData.size()),
+ "", "utf-8", XML_PARSE_NOENT));
if (!xmlDoc) {
*errorMessage = u"xmlParseMemory() failed for XML."_s;
return xml;
diff --git a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h
index 3430dce71..0dd8eafcb 100644
--- a/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h
+++ b/sources/shiboken6/ApiExtractor/xmlutils_libxslt.h
@@ -4,11 +4,12 @@
#define XMLUTILS_LIBXSLT_H
#include <QtCore/QString>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
class XQuery;
-QSharedPointer<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage);
+std::shared_ptr<XQuery> libXml_createXQuery(const QString &focus, QString *errorMessage);
QString libXslt_transform(const QString &xml, QString xsl, QString *errorMessage);
diff --git a/sources/shiboken6/ApiExtractor/xmlutils_qt.h b/sources/shiboken6/ApiExtractor/xmlutils_qt.h
index f0c51915f..274827044 100644
--- a/sources/shiboken6/ApiExtractor/xmlutils_qt.h
+++ b/sources/shiboken6/ApiExtractor/xmlutils_qt.h
@@ -4,11 +4,12 @@
#define XMLUTILS_QT_H
#include <QtCore/QString>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
class XQuery;
-QSharedPointer<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage);
+std::shared_ptr<XQuery> qt_createXQuery(const QString &focus, QString *errorMessage);
QString qt_xsl_transform(const QString &xml, QString xsl, QString *errorMessage);
diff --git a/sources/shiboken6/CMakeLists.txt b/sources/shiboken6/CMakeLists.txt
index a6ed7681b..9e1bb09b3 100644
--- a/sources/shiboken6/CMakeLists.txt
+++ b/sources/shiboken6/CMakeLists.txt
@@ -1,15 +1,21 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
Include(icecc.cmake)
-cmake_minimum_required(VERSION 3.16)
-cmake_policy(VERSION 3.16)
+cmake_minimum_required(VERSION 3.18)
+cmake_policy(VERSION 3.18)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build Type")
include(".cmake.conf")
project(shiboken6)
-
include(cmake/ShibokenSetup.cmake)
+get_rpath_base_token(base)
+
+set(CMAKE_INSTALL_RPATH ${base}/)
+
if(SHIBOKEN_BUILD_TOOLS)
add_subdirectory(ApiExtractor) # Uses libclang
add_subdirectory(generator) # Uses ApiExtractor And QtCore
diff --git a/sources/shiboken6/cmake/FindDocTools.cmake b/sources/shiboken6/cmake/FindDocTools.cmake
index abf5e5005..621a4ac15 100644
--- a/sources/shiboken6/cmake/FindDocTools.cmake
+++ b/sources/shiboken6/cmake/FindDocTools.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
find_program(SPHINX_BUILD sphinx-build DOC "Path to sphinx-build binary.")
# graphviz dot appears to be used by sphinx and not by CMake directly. This is just found to check
diff --git a/sources/shiboken6/cmake/ShibokenHelpers.cmake b/sources/shiboken6/cmake/ShibokenHelpers.cmake
index 567a79c62..8bc066102 100644
--- a/sources/shiboken6/cmake/ShibokenHelpers.cmake
+++ b/sources/shiboken6/cmake/ShibokenHelpers.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include(CMakeParseArguments)
macro(set_limited_api)
@@ -12,7 +15,7 @@ endmacro()
macro(set_debug_build)
set(SHIBOKEN_BUILD_TYPE "Debug")
- if(NOT PYTHON_DEBUG_LIBRARIES)
+ if(NOT Python_LIBRARIES)
message(WARNING "Python debug shared library not found; \
assuming python was built with shared library support disabled.")
endif()
@@ -50,9 +53,14 @@ if(MSVC)
set(CMAKE_CXX_FLAGS "/Zc:wchar_t /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS")
#set(CMAKE_CXX_FLAGS "/Zc:wchar_t /GR /EHsc /DNOCOLOR /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") # XXX
else()
+ set (gcc_warnings_options "-Wall -Wextra -Wno-strict-aliasing")
+ # Clang has -Wno-bad-function-cast, but does not need it.
+ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ set (gcc_warnings_options "${gcc_warnings_options} -Wno-cast-function-type")
+ endif()
if(CMAKE_HOST_UNIX AND NOT CYGWIN)
add_definitions(-fPIC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${gcc_warnings_options} -fvisibility=hidden")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "-g")
option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library \
@@ -108,7 +116,7 @@ macro(shiboken_internal_set_python_site_packages)
endif()
else()
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ COMMAND ${Python_EXECUTABLE} -c "if True:
import sysconfig
from os.path import sep
@@ -194,6 +202,12 @@ macro(get_python_extension_suffix)
# Python_SOABI is only set by CMake 3.17+
# TODO: Lower this to CMake 3.16 if possible.
if(SHIBOKEN_IS_CROSS_BUILD)
+ # For android platform armv7a FindPython module return Python_SOABI as empty because
+ # it is unable to set Python_CONFIG i.e. find `python3-config` script
+ # This workaround sets the Python_SOABI manually for this platform.
+ if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a")
+ set(Python_SOABI "cpython-311}")
+ endif()
if(NOT Python_SOABI)
message(FATAL_ERROR "Python_SOABI variable is empty.")
endif()
@@ -201,7 +215,7 @@ macro(get_python_extension_suffix)
else()
# See PYSIDE-1841 / https://bugs.python.org/issue39825 for distutils vs sysconfig
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ COMMAND ${Python_EXECUTABLE} -c "if True:
import sys
if sys.version_info >= (3, 8, 2):
import sysconfig
@@ -233,40 +247,44 @@ macro(shiboken_check_if_limited_api)
# TODO: Figure out how to use limited API libs when cross-building to Windows, if that's ever
# needed. Perhaps use host python to walk the libs of the target python installation.
- if(NOT SHIBOKEN_IS_CROSS_BUILD)
+ if(NOT SHIBOKEN_IS_CROSS_BUILD AND WIN32)
# On Windows, PYTHON_LIBRARIES can be a list. Example:
# optimized;C:/Python36/libs/python36.lib;debug;C:/Python36/libs/python36_d.lib
# On other platforms, this result is not used at all.
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c "if True:
- import os
- for lib in '${PYTHON_LIBRARIES}'.split(';'):
- if '/' in lib and os.path.isfile(lib):
- prefix, py = lib.rsplit('/', 1)
+ COMMAND ${Python_EXECUTABLE} -c "if True:
+ from pathlib import Path
+ libs = r'${Python_LIBRARIES}'
+ libs = libs.split(';')
+ for lib in libs:
+ if ('\\\\' in lib or '/' in lib) and Path(lib).is_file():
+ lib = Path(lib)
+ prefix = lib.parent
+ py = lib.name
if py.startswith('python3'):
- print(prefix + '/python3.lib')
+ print(prefix / 'python3.lib')
break
"
OUTPUT_VARIABLE PYTHON_LIMITED_LIBRARIES
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
- if(FORCE_LIMITED_API STREQUAL "yes")
- if (${PYTHON_VERSION_MAJOR} EQUAL 3 AND ${PYTHON_VERSION_MINOR} GREATER 4)
- # GREATER_EQUAL is available only from cmake 3.7 on. We mean python 3.5 .
- set(PYTHON_LIMITED_API 1)
- endif()
+ message(STATUS "PYTHON_LIMITED_LIBRARIES: " ${PYTHON_LIMITED_LIBRARIES})
+
+ if(FORCE_LIMITED_API OR SHIBOKEN_PYTHON_LIMITED_API)
+ set(PYTHON_LIMITED_API 1)
if(WIN32)
- if (${PYTHON_VERSION_MAJOR} EQUAL 3 AND ${PYTHON_VERSION_MINOR} GREATER 4)
- # PYSIDE-560: XXX maybe add an option to setup.py as override
- set(SHIBOKEN_PYTHON_LIBRARIES ${PYTHON_LIMITED_LIBRARIES})
- endif()
+ set(SHIBOKEN_PYTHON_LIBRARIES ${PYTHON_LIMITED_LIBRARIES})
endif()
endif()
endmacro()
macro(shiboken_find_required_python)
+ set(_shiboken_find_python_version_args "")
+ if(${ARGC} GREATER 0)
+ list(APPEND _shiboken_find_python_version_args "${ARGV0}")
+ endif()
# This function can also be called by consumers of ShibokenConfig.cmake package like pyside,
# that's why we also check for PYSIDE_IS_CROSS_BUILD (which is set by pyside project)
# and QFP_FIND_NEW_PYTHON_PACKAGE for an explicit opt in.
@@ -274,11 +292,6 @@ macro(shiboken_find_required_python)
# We have to use FindPython package instead of FindPythonInterp to get required target Python
# information.
if(SHIBOKEN_IS_CROSS_BUILD OR PYSIDE_IS_CROSS_BUILD OR QFP_FIND_NEW_PYTHON_PACKAGE)
- set(_shiboken_find_python_version_args "")
- if(${ARGC} GREATER 0)
- list(APPEND _shiboken_find_python_version_args "${ARGV0}")
- endif()
-
# We want FindPython to look in the sysroot for the python-config executable,
# but toolchain files might set CMAKE_FIND_ROOT_PATH_MODE_PROGRAM to NEVER because
# programs are mostly found for running and you usually can't run a target executable on
@@ -307,42 +320,25 @@ macro(shiboken_find_required_python)
"${_shiboken_backup_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM}")
set(CMAKE_FIND_ROOT_PATH
"${_shiboken_backup_CMAKE_FIND_ROOT_PATH}")
-
- # Mirror the variables that FindPythonInterp sets, instead of conditionally checking
- # and modifying all the places where the variables are used.
- set(PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
- set(PYTHON_VERSION "${Python_VERSION}")
- set(PYTHON_LIBRARIES "${Python_LIBRARIES}")
- set(PYTHON_INCLUDE_DIRS "${Python_INCLUDE_DIRS}")
- set(PYTHONINTERP_FOUND "${Python_Interpreter_FOUND}")
- set(PYTHONINTERP_FOUND "${Python_Interpreter_FOUND}")
- set(PYTHONLIBS_FOUND "${Python_Development_FOUND}")
- set(PYTHON_VERSION_MAJOR "${Python_VERSION_MAJOR}")
- set(PYTHON_VERSION_MINOR "${Python_VERSION_MINOR}")
- set(PYTHON_VERSION_PATCH "${Python_VERSION_PATCH}")
else()
- if(${ARGC} GREATER 0)
- find_package(PythonInterp ${ARGV0} REQUIRED)
- find_package(PythonLibs ${ARGV0} REQUIRED)
- else()
- # If no version is specified, just use any interpreter that can be found (from PATH).
- # This is useful for super-project builds, so that the default system interpeter
- # gets picked up (e.g. /usr/bin/python and not /usr/bin/python2.7).
- find_package(PythonInterp REQUIRED)
- find_package(PythonLibs REQUIRED)
- endif()
+ find_package(
+ Python
+ ${_shiboken_find_python_version_args}
+ REQUIRED
+ COMPONENTS Interpreter Development
+ )
endif()
shiboken_validate_python_version()
- set(SHIBOKEN_PYTHON_INTERPRETER "${PYTHON_EXECUTABLE}")
- set_property(GLOBAL PROPERTY SHIBOKEN_PYTHON_INTERPRETER "${PYTHON_EXECUTABLE}")
+ set(SHIBOKEN_PYTHON_INTERPRETER "${Python_EXECUTABLE}")
+ set_property(GLOBAL PROPERTY SHIBOKEN_PYTHON_INTERPRETER "${Python_EXECUTABLE}")
endmacro()
macro(shiboken_validate_python_version)
- if(PYTHON_VERSION_MAJOR EQUAL "3" AND PYTHON_VERSION_MINOR LESS "5")
+ if(Python_VERSION_MAJOR EQUAL "3" AND Python_VERSION_MINOR LESS "7")
message(FATAL_ERROR
- "Shiboken requires Python 3.5+.")
+ "Shiboken requires Python 3.7+.")
endif()
endmacro()
@@ -361,14 +357,14 @@ macro(shiboken_compute_python_includes)
if (SHIBOKEN_COMPUTE_INCLUDES_IS_CALLED_FROM_EXPORT)
#TODO target_include_directories works on imported targets only starting with v3.11.0.
set_property(TARGET Shiboken6::libshiboken
- APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS})
+ APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Python_INCLUDE_DIRS})
else()
target_include_directories(libshiboken
- PUBLIC $<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>)
+ PUBLIC $<BUILD_INTERFACE:${Python_INCLUDE_DIRS}>)
endif()
- set(SHIBOKEN_PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}")
+ set(SHIBOKEN_PYTHON_INCLUDE_DIRS "${Python_INCLUDE_DIRS}")
set_property(GLOBAL PROPERTY shiboken_python_include_dirs "${SHIBOKEN_PYTHON_INCLUDE_DIRS}")
@@ -428,16 +424,8 @@ macro(shiboken_compute_python_libraries)
set(SHIBOKEN_PYTHON_LIBRARIES "")
endif()
- if(CMAKE_BUILD_TYPE STREQUAL "Debug")
- if(WIN32 AND NOT SHIBOKEN_PYTHON_LIBRARIES)
- set(SHIBOKEN_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES})
- endif()
- endif()
-
- if(CMAKE_BUILD_TYPE STREQUAL "Release")
- if(WIN32 AND NOT SHIBOKEN_PYTHON_LIBRARIES)
- set(SHIBOKEN_PYTHON_LIBRARIES ${PYTHON_LIBRARIES})
- endif()
+ if(WIN32 AND NOT SHIBOKEN_PYTHON_LIBRARIES)
+ set(SHIBOKEN_PYTHON_LIBRARIES ${Python_LIBRARIES})
endif()
# If the resulting variable
@@ -470,20 +458,20 @@ macro(shiboken_compute_python_libraries)
endmacro()
function(shiboken_check_if_built_and_target_python_are_compatible)
- if(NOT SHIBOKEN_PYTHON_VERSION_MAJOR STREQUAL PYTHON_VERSION_MAJOR)
+ if(NOT SHIBOKEN_PYTHON_VERSION_MAJOR STREQUAL Python_VERSION_MAJOR)
message(FATAL_ERROR "The detected Python major version is not \
compatible with the Python major version which was used when Shiboken was built.
Built with: '${SHIBOKEN_PYTHON_VERSION_MAJOR}.${SHIBOKEN_PYTHON_VERSION_MINOR}' \
-Detected: '${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}'")
+Detected: '${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}'")
else()
if(NOT SHIBOKEN_PYTHON_LIMITED_API
- AND NOT SHIBOKEN_PYTHON_VERSION_MINOR STREQUAL PYTHON_VERSION_MINOR)
+ AND NOT SHIBOKEN_PYTHON_VERSION_MINOR STREQUAL Python_VERSION_MINOR)
message(FATAL_ERROR
"The detected Python minor version is not compatible with the Python minor \
version which was used when Shiboken was built. Consider building shiboken with \
FORCE_LIMITED_API set to '1', so that only the Python major version matters.
Built with: '${SHIBOKEN_PYTHON_VERSION_MAJOR}.${SHIBOKEN_PYTHON_VERSION_MINOR}' \
-Detected: '${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}'")
+Detected: '${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}'")
endif()
endif()
endfunction()
@@ -594,6 +582,17 @@ endfunction()
macro(compute_config_py_values
full_version_var_name
)
+ set(QT_MACOS_DEPLOYMENT_TARGET "")
+ if (Qt${QT_MAJOR_VERSION}Core_FOUND)
+ get_target_property(darwin_target Qt6::Core QT_DARWIN_MIN_DEPLOYMENT_TARGET)
+ if(darwin_target)
+ set(QT_MACOS_DEPLOYMENT_TARGET
+ "__qt_macos_min_deployment_target__ = '${darwin_target}'")
+ endif()
+ elseif(APPLE)
+ message(FATAL_ERROR "Qt6::Core should be found before calling this macro")
+ endif()
+
string(TIMESTAMP PACKAGE_BUILD_DATE "%Y-%m-%dT%H:%M:%S+00:00" UTC)
if (PACKAGE_BUILD_DATE)
set(PACKAGE_BUILD_DATE "__build_date__ = '${PACKAGE_BUILD_DATE}'")
@@ -669,3 +668,217 @@ macro(create_generator_target library_name)
add_custom_target(${library_name}_generator DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log")
add_dependencies(${library_name} ${library_name}_generator)
endmacro()
+
+# Generate a shell script wrapper that sets environment variables for executing a specific tool.
+#
+# tool_name should be a unique tool name, preferably without spaces.
+# Returns the wrapper path in path_out_var.
+#
+# Currently adds the Qt lib dir and libclang to PATH / LD_LIBRARY_PATH / DYLD_LIBRARY_PATH.
+# Meant to be used as the first argument to add_custom_command's COMMAND option.
+# TODO: Remove tool_name as the tool_name for this function is always shiboken.
+function(shiboken_get_tool_shell_wrapper tool_name path_out_var)
+ # Generate the wrapper only once during the execution of CMake.
+ get_property(is_called GLOBAL PROPERTY "_shiboken_tool_wrapper_${tool_name}_created")
+
+ if(is_called)
+ get_property(wrapper_path GLOBAL PROPERTY "_shiboken_tool_wrapper_${tool_name}_path")
+ set(${path_out_var} "${wrapper_path}" PARENT_SCOPE)
+ return()
+ endif()
+
+ set(path_dirs "")
+ set(path_dirs_native "")
+
+ if(CMAKE_HOST_WIN32)
+ set(wrapper_script_extension ".bat")
+ else()
+ set(wrapper_script_extension ".sh")
+ endif()
+
+ # Try to get original host shiboken paths from exported target properties.
+ shiboken_get_host_tool_wrapper_properties(orig_qt_library_dir_absolute orig_libclang_lib_dir)
+
+ # Get path to the Qt bin/lib dir depending on the platform and developer input.
+ # Prefer values given on the command line, then the original host path if it exists, otherwise
+ # try to use the Qt install prefix and libclang env vars.
+ #
+ # Note that in a cross-compiling case, using the Qt install prefix is very likely
+ # wrong, because you want to use the location of the host Qt, not the target Qt. Same for
+ # libclang. Unfortunately we currently don't provide a host Qt and host libclang option via
+ # setup.py, so the manual cmake vars will have to suffice.
+ if(SHIBOKEN_WRAPPER_HOST_QT_LIB_PATH AND EXISTS "${SHIBOKEN_WRAPPER_HOST_QT_LIB_PATH}")
+ set(qt_library_dir_absolute "${SHIBOKEN_WRAPPER_HOST_QT_LIB_PATH}")
+ elseif(orig_qt_library_dir_absolute AND EXISTS "${orig_qt_library_dir_absolute}")
+ set(qt_library_dir_absolute "${orig_qt_library_dir_absolute}")
+ elseif(CMAKE_HOST_WIN32)
+ # in Windows the Qt dll are store `bin` in directory
+ set(qt_library_dir ${QT6_INSTALL_BINS})
+ else()
+ # in Unix the .so are stored in `lib` directory
+ set(qt_library_dir ${QT6_INSTALL_LIBS})
+ endif()
+
+ # Assert that Qt is already found.
+ if((QT6_INSTALL_PREFIX AND qt_library_dir) OR orig_qt_library_dir_absolute)
+ else()
+ message(FATAL_ERROR "Qt should have been found already by now.")
+ endif()
+
+ if(NOT qt_library_dir_absolute)
+ set(qt_library_dir_absolute "${QT6_INSTALL_PREFIX}/${qt_library_dir}")
+ endif()
+ list(APPEND path_dirs "${qt_library_dir_absolute}")
+
+ # Get libclang lib dir path.
+ # Prefer values given on the command line, then the original host path if it exists.
+ if(SHIBOKEN_WRAPPER_HOST_CLANG_LIB_PATH AND EXISTS "${SHIBOKEN_WRAPPER_HOST_CLANG_LIB_PATH}")
+ set(libclang_lib_dir "${SHIBOKEN_WRAPPER_HOST_CLANG_LIB_PATH}")
+ elseif(orig_libclang_lib_dir AND EXISTS "${orig_libclang_lib_dir}")
+ set(libclang_lib_dir "${orig_libclang_lib_dir}")
+ else()
+ # find libclang
+ find_libclang()
+ endif()
+
+ if(libclang_lib_dir)
+ list(APPEND path_dirs "${libclang_lib_dir}")
+ endif()
+
+ # Convert the paths from unix-style to native Windows style.
+ foreach(path_dir IN LISTS path_dirs)
+ if(EXISTS "${path_dir}")
+ file(TO_NATIVE_PATH "${path_dir}" path_dir_native)
+ list(APPEND path_dirs_native "${path_dir_native}")
+ endif()
+ endforeach()
+
+ set(wrapper_dir "${CMAKE_BINARY_DIR}/.qfp/bin")
+ file(MAKE_DIRECTORY "${wrapper_dir}")
+ set(wrapper_path "${wrapper_dir}/${tool_name}_wrapper${wrapper_script_extension}")
+
+ if(CMAKE_HOST_WIN32)
+ file(WRITE "${wrapper_path}" "@echo off
+set PATH=${path_dirs_native};%PATH%
+%*")
+ elseif(CMAKE_HOST_APPLE)
+ string(REPLACE ";" ":" path_dirs_native "${path_dirs_native}")
+ file(WRITE "${wrapper_path}" "#!/bin/bash
+export DYLD_LIBRARY_PATH=${path_dirs_native}:$DYLD_LIBRARY_PATH
+export DYLD_FRAMEWORK_PATH=${path_dirs_native}:$DYLD_FRAMEWORK_PATH
+$@")
+ else()
+ string(REPLACE ";" ":" path_dirs_native "${path_dirs_native}")
+ file(WRITE "${wrapper_path}" "#!/bin/bash
+export LD_LIBRARY_PATH=${path_dirs_native}:$LD_LIBRARY_PATH
+$@")
+ endif()
+
+ # Remember the creation of the file for a specific tool.
+ set_property(GLOBAL PROPERTY "_shiboken_tool_wrapper_${tool_name}_path" "${wrapper_path}")
+ set_property(GLOBAL PROPERTY "_shiboken_tool_wrapper_${tool_name}_created" TRUE)
+
+ # Save original host paths for future cross-builds.
+ shiboken_save_host_tool_wrapper_properties("${qt_library_dir_absolute}" "${libclang_lib_dir}")
+
+ # give execute permission to run the file
+ if(CMAKE_HOST_UNIX)
+ execute_process(COMMAND chmod +x ${wrapper_path})
+ endif()
+
+ set(${path_out_var} "${wrapper_path}" PARENT_SCOPE)
+endfunction()
+
+# Retrieve the original host shiboken runtime dependency paths from the installed (namespaced)
+# shiboken generator target.
+function(shiboken_get_host_tool_wrapper_properties out_qt_library_dir out_libclang_lib_dir)
+ if(TARGET Shiboken6::shiboken6)
+ get_target_property(qt_library_dir Shiboken6::shiboken6 _shiboken_original_qt_lib_dir)
+ if(NOT qt_library_dir)
+ set(qt_library_dir "")
+ endif()
+ get_target_property(libclang_lib_dir Shiboken6::shiboken6
+ _shiboken_original_libclang_lib_dir)
+ if(NOT libclang_lib_dir)
+ set(libclang_lib_dir "")
+ endif()
+ endif()
+
+ set(${out_qt_library_dir} "${qt_library_dir}" PARENT_SCOPE)
+ set(${out_libclang_lib_dir} "${libclang_lib_dir}" PARENT_SCOPE)
+endfunction()
+
+# Save original host shiboken runtime dependency paths as target properties, so they can be used
+# when generating the wrapper file for cross-builds.
+# Should only be done when shiboken is being built (aka it's a non-imported target).
+function(shiboken_save_host_tool_wrapper_properties qt_library_dir libclang_lib_dir)
+ if(TARGET shiboken6)
+ get_target_property(is_imported shiboken6 IMPORTED)
+ if(is_imported)
+ return()
+ endif()
+
+ set_target_properties(shiboken6 PROPERTIES
+ _shiboken_original_qt_lib_dir "${qt_library_dir}")
+ set_property(TARGET shiboken6 APPEND PROPERTY
+ EXPORT_PROPERTIES _shiboken_original_qt_lib_dir)
+ if(libclang_lib_dir)
+ set_target_properties(shiboken6 PROPERTIES
+ _shiboken_original_libclang_lib_dir "${libclang_lib_dir}")
+ set_property(TARGET shiboken6 APPEND PROPERTY
+ EXPORT_PROPERTIES _shiboken_original_libclang_lib_dir)
+ endif()
+ endif()
+endfunction()
+
+# Returns the platform-specific relative rpath base token, if it's supported.
+# If it's not supported, returns the string NO_KNOWN_RPATH_REL_BASE.
+function(get_rpath_base_token out_var)
+ if(APPLE)
+ set(rpath_rel_base "@loader_path")
+ elseif(UNIX)
+ set(rpath_rel_base "$ORIGIN")
+ else()
+ #has no effect on Windows
+ set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE")
+ endif()
+ set(${out_var} "${rpath_rel_base}" PARENT_SCOPE)
+endfunction()
+
+# Get path to libclang.dll/libclang.so depending on the platform
+macro(find_libclang)
+ if(CMAKE_HOST_WIN32)
+ set(libclang_directory_suffix "bin")
+ set(libclang_suffix ".dll")
+ else()
+ set(libclang_directory_suffix "lib")
+ if(CMAKE_HOST_APPLE)
+ set(libclang_suffix ".dylib")
+ else()
+ set(libclang_suffix ".so")
+ endif()
+ endif()
+
+ set(libclang_lib_dir "")
+ if(DEFINED ENV{LLVM_INSTALL_DIR})
+ set(libclang_lib_dir "$ENV{LLVM_INSTALL_DIR}/${libclang_directory_suffix}")
+ elseif(DEFINED ENV{CLANG_INSTALL_DIR})
+ set(libclang_lib_dir "$ENV{CLANG_INSTALL_DIR}/${libclang_directory_suffix}")
+ else()
+ message(WARNING
+ "Couldn't find libclang${libclang_suffix} "
+ "You will likely need to add it manually to PATH to ensure the build succeeds.")
+ endif()
+endmacro()
+
+# Allow setting a shiboken debug level from the the build system or from the environment
+# to all shiboken invocations.
+function(shiboken_get_debug_level out_var)
+ set(debug_level "")
+ if(SHIBOKEN_DEBUG_LEVEL)
+ set(debug_level "--debug-level=${SHIBOKEN_DEBUG_LEVEL}")
+ elseif(DEFINED $ENV{SHIBOKEN_DEBUG_LEVEL})
+ set(debug_level "--debug-level=$ENV{SHIBOKEN_DEBUG_LEVEL}")
+ endif()
+ set(${out_var} "${debug_level}" PARENT_SCOPE)
+endfunction()
diff --git a/sources/shiboken6/cmake/ShibokenSetup.cmake b/sources/shiboken6/cmake/ShibokenSetup.cmake
index 76bf86a10..32823d9fa 100644
--- a/sources/shiboken6/cmake/ShibokenSetup.cmake
+++ b/sources/shiboken6/cmake/ShibokenSetup.cmake
@@ -1,21 +1,19 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include(CheckIncludeFileCXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
include(ShibokenHelpers)
-option(USE_PYTHON_VERSION "Use specific python version to build shiboken6." "")
option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE)
shiboken_internal_disable_pkg_config_if_needed()
shiboken_internal_detect_if_cross_building()
-if(SHIBOKEN_IS_CROSS_BUILD AND CMAKE_VERSION VERSION_LESS "3.17")
- # TODO: We rely on FindPython shipped with CMake 3.17+ to provide the value of Python_SOABI.
- # It might be possible to extract the Python_SOABI manually with CMake 3.16 if we reimplement
- # the logic that FindPython does in 3.17 ourselves.
- message(FATAL_ERROR "You need CMake version 3.17 or greater to cross-build.")
-endif()
+# Note: For cross building, we rely on FindPython shipped with CMake 3.17+ to
+# provide the value of Python_SOABI.
shiboken_internal_decide_parts_to_build()
shiboken_internal_find_host_shiboken_tools()
@@ -23,7 +21,7 @@ shiboken_internal_set_up_extra_dependency_paths()
set(QT_MAJOR_VERSION 6)
message(STATUS "Using Qt ${QT_MAJOR_VERSION}")
-find_package(Qt${QT_MAJOR_VERSION} 6.0 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
if(QUIET_BUILD)
set_quiet_build()
@@ -45,13 +43,12 @@ set(shiboken6_library_so_version "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VER
compute_config_py_values(shiboken6_VERSION)
## For debugging the PYTHON* variables
-message(STATUS "PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND})
-message(STATUS "PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES})
-message(STATUS "PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS})
-message(STATUS "PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES})
-message(STATUS "PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND})
-message(STATUS "PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE})
-message(STATUS "PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH})
+message(STATUS "Python_Development_FOUND: " ${Python_Development_FOUND})
+message(STATUS "Python_LIBRARIES: " ${Python_LIBRARIES})
+message(STATUS "Python_INCLUDE_DIRS: " ${Python_INCLUDE_DIRS})
+message(STATUS "Python_Interpreter_FOUND: " ${Python_Interpreter_FOUND})
+message(STATUS "Python_EXECUTABLE: " ${Python_EXECUTABLE})
+message(STATUS "Python_VERSION: " ${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}.${Python_VERSION_PATCH})
if(NOT PYTHON_EXTENSION_SUFFIX)
get_python_extension_suffix()
@@ -107,7 +104,7 @@ endif()
if(CMAKE_HOST_APPLE)
set(OSX_USE_LIBCPP "OFF" CACHE BOOL "Explicitly link the libc++ standard library \
- (useful for osx deployment targets lower than 10.9.")
+ (useful for macOS deployment targets lower than 10.9.")
if(OSX_USE_LIBCPP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
@@ -122,7 +119,7 @@ endif()
# Detect if the python libs were compiled in debug mode
# On Linux distros there is no standard way to check that.
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ COMMAND ${Python_EXECUTABLE} -c "if True:
import sys
import sysconfig
config_py_debug = sysconfig.get_config_var('Py_DEBUG')
@@ -140,7 +137,7 @@ if(SHIBOKEN_IS_CROSS_BUILD)
set(PYTHON_WITH_COUNT_ALLOCS 0)
else()
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ COMMAND ${Python_EXECUTABLE} -c "if True:
count_allocs = False
import sys
try:
@@ -183,7 +180,6 @@ set(shiboken_python_files
"signature/parser.py"
"__init__.py"
"feature.py"
- "enum_310.py"
)
# uninstall target
diff --git a/sources/shiboken6/cmake_uninstall.cmake b/sources/shiboken6/cmake_uninstall.cmake
index df95fb9d8..4031b4e1a 100644
--- a/sources/shiboken6/cmake_uninstall.cmake
+++ b/sources/shiboken6/cmake_uninstall.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
diff --git a/sources/shiboken6/config.tests/target_python_info/CMakeLists.txt b/sources/shiboken6/config.tests/target_python_info/CMakeLists.txt
index 55fafb7c3..b3f994017 100644
--- a/sources/shiboken6/config.tests/target_python_info/CMakeLists.txt
+++ b/sources/shiboken6/config.tests/target_python_info/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
project(proj LANGUAGES CXX)
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/ShibokenHelpers.cmake")
diff --git a/sources/shiboken6/config.tests/target_qt_info/CMakeLists.txt b/sources/shiboken6/config.tests/target_qt_info/CMakeLists.txt
index bb0e11b9e..7cc6b6ffc 100644
--- a/sources/shiboken6/config.tests/target_qt_info/CMakeLists.txt
+++ b/sources/shiboken6/config.tests/target_qt_info/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
project(proj LANGUAGES CXX)
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/ShibokenHelpers.cmake")
diff --git a/sources/shiboken6/config.tests/target_qt_mkspec/CMakeLists.txt b/sources/shiboken6/config.tests/target_qt_mkspec/CMakeLists.txt
index 033369188..9f6513316 100644
--- a/sources/shiboken6/config.tests/target_qt_mkspec/CMakeLists.txt
+++ b/sources/shiboken6/config.tests/target_qt_mkspec/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
project(dummy LANGUAGES CXX)
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/ShibokenHelpers.cmake")
diff --git a/sources/shiboken6/data/CMakeLists.txt b/sources/shiboken6/data/CMakeLists.txt
index 80dd7ca36..679eefe6a 100644
--- a/sources/shiboken6/data/CMakeLists.txt
+++ b/sources/shiboken6/data/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX})
else()
@@ -29,7 +32,7 @@ endif()
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/Shiboken6Config-spec.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/install/Shiboken6Config${PYTHON_CONFIG_SUFFIX}.cmake"
- INSTALL_DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION}"
+ INSTALL_DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6"
PATH_VARS SHIBOKEN_PYTHON_MODULE_DIR SHIBOKEN_SHARED_LIBRARY_DIR
)
@@ -41,16 +44,16 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken6.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/shiboken6${shiboken6_SUFFIX}.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken6Config.cmake"
- DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION}")
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/install/Shiboken6Config${PYTHON_CONFIG_SUFFIX}.cmake"
- DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION}")
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken6ConfigVersion.cmake"
- DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION}")
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ShibokenHelpers.cmake"
- DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION}")
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken6")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shiboken6${shiboken6_SUFFIX}.pc"
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
diff --git a/sources/shiboken6/data/Shiboken6Config-spec.cmake.in b/sources/shiboken6/data/Shiboken6Config-spec.cmake.in
index a07563a53..233404bc6 100644
--- a/sources/shiboken6/data/Shiboken6Config-spec.cmake.in
+++ b/sources/shiboken6/data/Shiboken6Config-spec.cmake.in
@@ -5,9 +5,9 @@
# This is the version of Python against which Shiboken was built. Not necessarily the version
# against which a downstream project is built (e.g. PySide6).
-set(SHIBOKEN_PYTHON_VERSION_MAJOR "@PYTHON_VERSION_MAJOR@")
-set(SHIBOKEN_PYTHON_VERSION_MINOR "@PYTHON_VERSION_MINOR@")
-set(SHIBOKEN_PYTHON_VERSION_PATCH "@PYTHON_VERSION_PATCH@")
+set(SHIBOKEN_PYTHON_VERSION_MAJOR "@Python_VERSION_MAJOR@")
+set(SHIBOKEN_PYTHON_VERSION_MINOR "@Python_VERSION_MINOR@")
+set(SHIBOKEN_PYTHON_VERSION_PATCH "@Python_VERSION_PATCH@")
set(SHIBOKEN_PYTHON_LIMITED_API "@PYTHON_LIMITED_API@")
# Import targets and call variable set up functions only when using an installed shiboken config
@@ -17,7 +17,7 @@ if (NOT TARGET Shiboken6::libshiboken)
include("${CMAKE_CURRENT_LIST_DIR}/ShibokenHelpers.cmake")
# Compute the python include and libraries path if needed (aka not part of super project build).
- shiboken_find_required_python(@PYTHON_VERSION_MAJOR@)
+ shiboken_find_required_python(@Python_VERSION_MAJOR@)
shiboken_check_if_built_and_target_python_are_compatible()
shiboken_check_if_limited_api()
shiboken_compute_python_includes(IS_CALLED_FROM_EXPORT)
diff --git a/sources/shiboken6/data/Shiboken6ToolsConfig.cmake.in b/sources/shiboken6/data/Shiboken6ToolsConfig.cmake.in
index 84ccf622f..438b5c651 100644
--- a/sources/shiboken6/data/Shiboken6ToolsConfig.cmake.in
+++ b/sources/shiboken6/data/Shiboken6ToolsConfig.cmake.in
@@ -1,6 +1,6 @@
@PACKAGE_INIT@
-cmake_minimum_required(VERSION 3.16)
+cmake_minimum_required(VERSION 3.18)
if(NOT TARGET Shiboken6::shiboken6)
include("${CMAKE_CURRENT_LIST_DIR}/Shiboken6ToolsTargets.cmake")
diff --git a/sources/shiboken6/data/shiboken6.pc.in b/sources/shiboken6/data/shiboken6.pc.in
index d05fe8991..a82d23168 100644
--- a/sources/shiboken6/data/shiboken6.pc.in
+++ b/sources/shiboken6/data/shiboken6.pc.in
@@ -1,12 +1,12 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
-libdir=@LIB_INSTALL_DIR@
+libdir=@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_DIR@
includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken6
-python_interpreter=@PYTHON_EXECUTABLE@
-python_include_dir=@PYTHON_INCLUDE_DIRS@
+python_interpreter=@Python_EXECUTABLE@
+python_include_dir=@Python_INCLUDE_DIRS@
Name: shiboken6
Description: Support library for Python bindings created with the Shiboken6 generator.
Version: @shiboken6_VERSION@
Libs: @SHIBOKEN_PYTHON_LIBRARIES@ -L${libdir} -lshiboken6@shiboken6_SUFFIX@@PYTHON_SHARED_LIBRARY_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@
-Cflags: -I@PYTHON_INCLUDE_DIRS@ -I${includedir}/@shiboken6_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@
+Cflags: -I@Python_INCLUDE_DIRS@ -I${includedir}/@shiboken6_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@
diff --git a/sources/shiboken6/doc/CMakeLists.txt b/sources/shiboken6/doc/CMakeLists.txt
index 4cd459c23..eaef4ff29 100644
--- a/sources/shiboken6/doc/CMakeLists.txt
+++ b/sources/shiboken6/doc/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
if(FULLDOCSBUILD EQUAL 0)
project(shiboken6_doc)
@@ -18,7 +21,7 @@ if(SPHINX_BUILD)
# conditional tag for sphinx build
#string(JOIN "_" SPHINX_TAG ${DOC_OUTPUT_FORMAT} "format")
add_custom_target(doc
- COMMAND ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} -c . ${CMAKE_CURRENT_SOURCE_DIR} html
+ COMMAND ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} -j auto -c . ${CMAKE_CURRENT_SOURCE_DIR} html
COMMENT "Generating shiboken documentation HTML files"
VERBATIM)
@@ -34,14 +37,14 @@ if(SPHINX_BUILD)
if(SHIBOKEN_IS_CROSS_BUILD)
set(python_executable "${QFP_PYTHON_HOST_PATH}")
else()
- set(python_executable "${PYTHON_EXECUTABLE}")
+ set(python_executable "${Python_EXECUTABLE}")
endif()
if(NOT python_executable OR NOT EXISTS "${python_executable}")
message(FATAL_ERROR "No python executable found to build documentation.")
endif()
add_custom_command(TARGET doc POST_BUILD
- COMMAND "${python_executable}" ${PATCH_QHP_SCRIPT} -f ${QHP_FILE} -v shiboken6
+ COMMAND "${python_executable}" ${PATCH_QHP_SCRIPT} -v shiboken6 ${QHP_FILE}
COMMAND "${qhelpgenerator_binary}" ${QHP_FILE}
COMMENT "Generating shiboken documentation QCH files based on the QHP files"
VERBATIM)
diff --git a/sources/shiboken6/doc/_static/css/qt_font.css b/sources/shiboken6/doc/_static/css/qt_font.css
index bc282785e..ce39943ef 100644
--- a/sources/shiboken6/doc/_static/css/qt_font.css
+++ b/sources/shiboken6/doc/_static/css/qt_font.css
@@ -4,6 +4,12 @@
font-weight: 400;
src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot");
/* IE9 Compat Modes */
- src: local("Titillium Web"), local("TitilliumWeb-Regular"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"), url("//d33sqmj vzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext- regular.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/ assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg");
+ src: local("Titillium Web"),
+ local("TitilliumWeb-Regular"),
+ url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"),
+ url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"),
+ url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff") format("woff"),
+ url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"),
+ url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg");
/* Legacy iOS */
}
diff --git a/sources/shiboken6/doc/_static/css/qt_style.css b/sources/shiboken6/doc/_static/css/qt_style.css
index ea40e5107..08c4646c6 100644
--- a/sources/shiboken6/doc/_static/css/qt_style.css
+++ b/sources/shiboken6/doc/_static/css/qt_style.css
@@ -1,37 +1,100 @@
-.btn-qt:hover,
-.btn-qt:active,
-.btn-qt:focus,
-.btn-qt.active {
- background: #41cd52;
- color: #fff !important;
- border-color: #fff;
+.text-center {
+ text-align: center !important;
}
-.btn-link {
- color: #41cd52 !important;
+.text-center img {
+ padding-top: 10px;
+ height: 70px !important;
}
-.btn-link:hover {
- color: #222840 !important;
- text-decoration: underline;
+.cover-img img {
+ object-fit: cover;
+ height: 50%;
}
-/* Using !important is not recommended, but out CSS is being added
- * to the pages before the bootstrap ones, so we cannot override them
- * without using it */
-.btn-qt {
- color: #41cd52 !important;
- border-color: #41cd52 !important;
- font-weight: bold !important;
+/* Tables */
+.section .docutils.container td {
+ float:left;
}
-.card-img-top-main {
- padding-top: 10px;
- height: 70px !important;
+
+table.docutils {
+ margin-right: auto;
+ margin-bottom: 10px;
+ border: none;
+ width: initial;
+ font-size: 0.8em;
+}
+
+table.docutils.colwidths-given td {
+ float: none;
+}
+
+table.docutils th,
+table.docutils td {
+ padding-left:0;
+ border: none;
+}
+
+table.docutils td ul {
+ margin:0
+}
+
+table.docutils td ul > li {
+ margin: 0 0 0.5em;
+}
+
+.hide {
+ display: none;
+}
+
+.fixed .container {
+ max-width:1280px;
+ margin:0 auto;
+ padding:0 3.9%; /* 0? */
+ position:relative;
+ overflow:visible
+}
+
+/* We cannot put a :download:`....` command inside
+ * a sphinx-design button, so we add some properties from the button
+ * to the download class to mimic it */
+code.download {
+ text-align: center;
+ color: var(--color-brand-primary);
+ display: block;
+ border-color: transparent;
+ background-color: transparent;
+ border: 1px solid var(--color-brand-primary) !important;
+ border-radius: 0.25rem;
+ font-size: 1rem;
+ font-weight: 400;
+ vertical-align: middle;
+ padding: .375rem .75rem;
+ user-select: none;
+ line-height: 1.5;
+ transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
+}
+
+code.download:hover {
+ color: white;
+ background-color: var(--color-brand-primary);
+ border-color: var(--color-brand-primary);
+ text-decoration: none;
+ padding: .375rem .75rem;
+}
+
+dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple):first-child > dt {
+ font-size: +2.25rem;
+ font-weight: 700;
+ color: #ff00dd;
+}
+
+.theme-toggle svg{
+ width: +1.25rem;
+ height: +2.25rem;
}
-.card-img-top {
- object-fit: contain;
- height: 120px;
- padding-top: 20px;
- transform: scale(1.3, 1.3);
+.sd-card-title code span {
+ font-size: +1rem;
+ color: var(--color-brand-primary);
}
diff --git a/sources/shiboken6/doc/_static/shiboken.png b/sources/shiboken6/doc/_static/shiboken.png
new file mode 100644
index 000000000..587d33329
--- /dev/null
+++ b/sources/shiboken6/doc/_static/shiboken.png
Binary files differ
diff --git a/sources/shiboken6/doc/_static/shiboken.svg b/sources/shiboken6/doc/_static/shiboken.svg
new file mode 100644
index 000000000..a13f3e9fb
--- /dev/null
+++ b/sources/shiboken6/doc/_static/shiboken.svg
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="1080"
+ zoomAndPan="magnify"
+ viewBox="0 0 810 809.999993"
+ height="1080"
+ preserveAspectRatio="xMidYMid meet"
+ version="1.0"
+ id="svg47"
+ sodipodi:docname="shiboken.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview49"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="0.80648148"
+ inkscape:cx="505.28129"
+ inkscape:cy="540"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg47" />
+ <defs
+ id="defs17">
+ <clipPath
+ id="25c649227a">
+ <path
+ d="M 187.234375 180.804688 L 622.011719 180.804688 L 622.011719 615.582031 L 187.234375 615.582031 Z M 187.234375 180.804688 "
+ clip-rule="nonzero"
+ id="path2" />
+ </clipPath>
+ <clipPath
+ id="a7a24c818d">
+ <path
+ d="M 475.953125 479.28125 L 728.5625 479.28125 L 728.5625 731.886719 L 475.953125 731.886719 Z M 475.953125 479.28125 "
+ clip-rule="nonzero"
+ id="path5" />
+ </clipPath>
+ <clipPath
+ id="9e94c67ce5">
+ <path
+ d="M 80.601562 479.28125 L 332.789062 479.28125 L 332.789062 731.886719 L 80.601562 731.886719 Z M 80.601562 479.28125 "
+ clip-rule="nonzero"
+ id="path8" />
+ </clipPath>
+ <clipPath
+ id="f807adb387">
+ <path
+ d="M 475.953125 81.417969 L 728.5625 81.417969 L 728.5625 333.609375 L 475.953125 333.609375 Z M 475.953125 81.417969 "
+ clip-rule="nonzero"
+ id="path11" />
+ </clipPath>
+ <clipPath
+ id="a7b91dab09">
+ <path
+ d="M 80.601562 81.417969 L 332.789062 81.417969 L 332.789062 333.609375 L 80.601562 333.609375 Z M 80.601562 81.417969 "
+ clip-rule="nonzero"
+ id="path14" />
+ </clipPath>
+ </defs>
+ <path
+ fill="#41cb51"
+ d="M 404.621094 459.0625 C 371.058594 459.0625 343.753906 431.75 343.753906 398.195312 C 343.753906 364.628906 371.058594 337.324219 404.621094 337.324219 C 438.179688 337.324219 465.492188 364.628906 465.492188 398.195312 C 465.492188 431.75 438.179688 459.0625 404.621094 459.0625 Z M 404.621094 459.0625 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path25" />
+ <g
+ clip-path="url(#25c649227a)"
+ id="g29">
+ <path
+ fill="#41cb51"
+ d="M 614.714844 363.132812 L 568.308594 355.550781 C 564.375 340.4375 558.351562 325.984375 550.351562 312.4375 L 577.464844 273.804688 C 579.890625 270.34375 579.480469 265.648438 576.5 262.65625 L 539.613281 225.769531 C 536.59375 222.742188 531.828125 222.371094 528.386719 224.855469 L 490.152344 252.335938 C 476.578125 244.351562 462.109375 238.34375 447.003906 234.4375 L 438.867188 187.996094 C 438.136719 183.839844 434.519531 180.804688 430.292969 180.804688 L 378.117188 180.804688 C 373.859375 180.804688 370.222656 183.890625 369.535156 188.101562 L 361.953125 234.535156 C 347.023438 238.421875 332.691406 244.371094 319.222656 252.273438 L 280.808594 224.820312 C 277.335938 222.351562 272.617188 222.742188 269.597656 225.742188 L 232.703125 262.628906 C 229.71875 265.613281 229.304688 270.308594 231.730469 273.761719 L 258.851562 312.5 C 250.886719 325.996094 244.902344 340.386719 240.980469 355.402344 L 194.511719 363.140625 C 190.3125 363.835938 187.234375 367.464844 187.234375 371.714844 L 187.234375 423.890625 C 187.234375 428.105469 190.261719 431.714844 194.40625 432.445312 L 240.894531 440.6875 C 244.78125 455.6875 250.746094 470.0625 258.675781 483.582031 L 231.214844 521.964844 C 228.746094 525.425781 229.136719 530.164062 232.136719 533.175781 L 269.023438 570.0625 C 272 573.035156 276.695312 573.453125 280.15625 571.035156 L 318.875 543.9375 C 332.320312 551.878906 346.703125 557.871094 361.78125 561.808594 L 369.535156 608.3125 C 370.242188 612.503906 373.867188 615.582031 378.117188 615.582031 L 430.292969 615.582031 C 434.5 615.582031 438.109375 612.554688 438.847656 608.40625 L 447.101562 561.914062 C 462.292969 557.984375 476.804688 551.949219 490.394531 543.921875 L 529.074219 571.035156 C 532.535156 573.460938 537.230469 573.050781 540.210938 570.070312 L 577.082031 533.183594 C 580.097656 530.164062 580.480469 525.410156 577.984375 521.957031 L 550.480469 483.730469 C 558.464844 470.175781 564.453125 455.714844 568.359375 440.609375 L 614.8125 432.460938 C 618.976562 431.722656 622.011719 428.105469 622.011719 423.890625 L 622.011719 371.714844 C 622.011719 367.453125 618.921875 363.820312 614.714844 363.132812 Z M 404.621094 502.539062 C 347.085938 502.539062 300.277344 455.722656 300.277344 398.183594 C 300.277344 340.65625 347.085938 293.847656 404.621094 293.847656 C 462.160156 293.847656 508.96875 340.65625 508.96875 398.183594 C 508.96875 455.722656 462.160156 502.539062 404.621094 502.539062 Z M 404.621094 502.539062 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path27" />
+ </g>
+ <g
+ clip-path="url(#a7a24c818d)"
+ id="g33">
+ <path
+ fill="#ffd43b"
+ d="M 653.035156 479.28125 C 653.035156 576.996094 573.667969 656.363281 475.953125 656.363281 L 475.953125 731.886719 C 615.484375 731.886719 728.5625 618.8125 728.5625 479.28125 Z M 653.035156 479.28125 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path31" />
+ </g>
+ <g
+ clip-path="url(#9e94c67ce5)"
+ id="g37">
+ <path
+ fill="#306998"
+ d="M 156.125 479.28125 C 156.125 576.996094 235.492188 656.363281 333.207031 656.363281 L 333.207031 731.886719 C 193.675781 731.886719 80.601562 618.8125 80.601562 479.28125 Z M 156.125 479.28125 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path35" />
+ </g>
+ <g
+ clip-path="url(#f807adb387)"
+ id="g41">
+ <path
+ fill="#306998"
+ d="M 653.035156 334.023438 C 653.035156 236.308594 573.667969 156.945312 475.953125 156.945312 L 475.953125 81.417969 C 615.484375 81.417969 728.5625 194.492188 728.5625 334.023438 Z M 653.035156 334.023438 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path39" />
+ </g>
+ <g
+ clip-path="url(#a7b91dab09)"
+ id="g45">
+ <path
+ fill="#ffd43b"
+ d="M 156.125 334.023438 C 156.125 236.308594 235.492188 156.945312 333.207031 156.945312 L 333.207031 81.417969 C 193.675781 81.417969 80.601562 194.492188 80.601562 334.023438 Z M 156.125 334.023438 "
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path43" />
+ </g>
+</svg>
diff --git a/sources/shiboken6/doc/_themes/pysidedocs_qthelp/static/pyside.css b/sources/shiboken6/doc/_themes/pysidedocs_qthelp/static/pyside.css
index aee5e4420..94134cacf 100644
--- a/sources/shiboken6/doc/_themes/pysidedocs_qthelp/static/pyside.css
+++ b/sources/shiboken6/doc/_themes/pysidedocs_qthelp/static/pyside.css
@@ -466,7 +466,7 @@ tt.descname {
position:relative
}
#menuextras li a:hover span {
- color: #41cd52;
+ color: #2cde85;
}
/* new header */
#mm-wrap, #mm-wrap #mm-helper,
@@ -557,14 +557,14 @@ tt.descname {
display:inline;
float:left;
width:31px;
- color:#41cd52
+ color:#2cde85
}
#navbar .navbar-oneQt:before {
content:attr(data-icon);
position:absolute;
top:14px;
left:0;
- color:#41cd52;
+ color:#2cde85;
font-family:'Qt Icons';
line-height:1;
font-size:40px;
@@ -1939,5 +1939,5 @@ table.special td {
.special td:hover {
padding-top: 2px;
padding-bottom: 2px;
- border-bottom: 4px solid #41cd52;
+ border-bottom: 4px solid #2cde85;
}
diff --git a/sources/shiboken6/doc/conf.py.in b/sources/shiboken6/doc/conf.py.in
index ca0b4963b..b10f33b2a 100644
--- a/sources/shiboken6/doc/conf.py.in
+++ b/sources/shiboken6/doc/conf.py.in
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# PyQtB documentation build configuration file, created by
+# Shiboken documentation build configuration file, created by
# sphinx-quickstart on Wed Apr 22 15:04:20 2009.
#
# This file is execfile()d with the current directory set to its containing dir.
@@ -11,34 +11,59 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-import sys, os
+import sys
+import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
+# documentation root, use Path(path).resolve() to make it absolute, like shown here.
+sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@')
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig',
- 'sphinx.ext.coverage', 'sphinx_panels', 'sphinx_copybutton']
+ 'sphinx.ext.coverage', 'sphinx.ext.intersphinx', 'sphinx.ext.todo',
+ 'sphinx.ext.graphviz',
+ 'sphinx.ext.viewcode',
+ 'sphinx_design', 'sphinx_copybutton',
+ 'myst_parser']
+
+myst_enable_extensions = [
+ "amsmath",
+ "colon_fence",
+ "deflist",
+ "dollarmath",
+ "fieldlist",
+ "html_admonition",
+ "html_image",
+ "replacements",
+ "smartquotes",
+ "strikethrough",
+ "substitution",
+ "tasklist",
+]
+myst_heading_anchors = 6
output_format='@DOC_OUTPUT_FORMAT@'
def setup(app):
app.add_config_value('output_format','qthelp','env')
-rst_epilog = """
-.. |project| replace:: Shiboken
+rst_epilog = """
+.. |project| replace:: Qt for Python
+.. |pymodname| replace:: Shiboken6
"""
# Add any paths that contain templates here, relative to this directory.
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates']
# The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = {
+ '.rst': 'restructuredtext',
+ '.md': 'markdown',
+}
# The encoding of source files.
source_encoding = 'utf-8'
@@ -48,16 +73,15 @@ master_doc = 'index'
# General information about the project.
project = u'Shiboken'
-copyright = u'2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 (https://www.gnu.org/licenses/fdl.html) as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.'
-
+copyright = u'2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 (https://www.gnu.org/licenses/fdl.html) as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '@shiboken_VERSION@'
+version = '@BINDING_API_VERSION@'
# The full version, including alpha/beta/rc tags.
-release = '@shiboken_VERSION@'
+release = '@BINDING_API_VERSION_FULL@'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -74,7 +98,8 @@ release = '@shiboken_VERSION@'
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
-exclude_trees = ['_build']
+exclude_patterns = ['_build',
+ '**README.md']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
@@ -109,16 +134,16 @@ html_theme = 'furo'
# documentation.
html_theme_options = {
"dark_css_variables": {
- "color-brand-primary": "#66689d",
- "color-brand-content": "#66689d",
- "color-admonition-title--important": "#41cd52",
+ "color-brand-primary": "#2cde85",
+ "color-brand-content": "#2cde85",
+ "color-admonition-title--important": "#2cde85",
"color-admonition-title-background--important": "#474b53",
"font-stack": "'Titillium Web', sans-serif",
},
"light_css_variables": {
- "color-brand-primary": "#66689d",
- "color-brand-content": "#41cd52",
- "color-admonition-title--important": "#41cd52",
+ "color-brand-primary": "#27138b",
+ "color-brand-content": "#27138b",
+ "color-admonition-title--important": "#27138b",
"font-stack": "'Titillium Web', sans-serif",
},
}
@@ -128,14 +153,14 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-#html_title = None
+html_title = "Shiboken"
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-html_logo = "@CMAKE_CURRENT_SOURCE_DIR@/_static/qtforpython.png"
+html_logo = "@CMAKE_CURRENT_SOURCE_DIR@/_static/shiboken.png"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -184,8 +209,3 @@ html_show_sourcelink = False
# -- Options for qthelp output --------------------------------------------------
qthelp_theme = 'pysidedocs_qthelp'
-
-# Sphinx Panels color for inactive tab
-panels_css_variables = {
- "tabs-color-label-inactive": "rgba(116, 116, 116, 1.0)",
-}
diff --git a/sources/shiboken6/doc/considerations.rst b/sources/shiboken6/doc/considerations.rst
index 1a406c7c9..ad913e7a6 100644
--- a/sources/shiboken6/doc/considerations.rst
+++ b/sources/shiboken6/doc/considerations.rst
@@ -6,6 +6,18 @@ Words of Advice
When writing or using Python bindings there is some things you must keep in mind.
+.. _rvalue_references:
+
+Rvalue References
+=================
+
+Normally, no bindings are generated for functions taking rvalue references.
+Experimental support has been added in 6.6. The functions need to be explicitly
+specified using the :ref:`add-function`, :ref:`declare-function` or
+:ref:`function` elements. For :ref:`value-type` objects, this does not have any
+implications since the arguments are copied in the generated code and the copy
+is moved from. For :ref:`object-type` objects however, it means that the object
+instance is moved from and should no longer be referenced.
.. _duck-punching-and-virtual-methods:
@@ -18,19 +30,19 @@ be tricky. That was an optimistic statement.
Let's see duck punching in action for educational purposes.
- .. code-block:: python
+.. code-block:: python
- import types
- import Binding
+ import types
+ import Binding
- obj = Binding.CppClass()
+ obj = Binding.CppClass()
- # CppClass has a virtual method called 'virtualMethod',
- # but we don't like it anymore.
- def myVirtualMethod(self_obj, arg):
- pass
+ # CppClass has a virtual method called 'virtualMethod',
+ # but we don't like it anymore.
+ def myVirtualMethod(self_obj, arg):
+ pass
- obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
+ obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
If some C++ code happens to call `CppClass::virtualMethod(...)` on the C++ object
@@ -46,17 +58,17 @@ Python-land by the usage of class constructors, like in the example above.
Brief interruption to show what I was saying:
- .. code-block:: python
+.. code-block:: python
- import types
- import Binding
+ import types
+ import Binding
- obj = Binding.createCppClass()
- def myVirtualMethod(self_obj, arg):
- pass
+ obj = Binding.createCppClass()
+ def myVirtualMethod(self_obj, arg):
+ pass
- # Punching a dead duck...
- obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
+ # Punching a dead duck...
+ obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
The `Binding.createCppClass()` factory method is just an example, C++ created objects
@@ -82,30 +94,30 @@ Below you can check the examples:
Example with old style class:
- .. code-block:: python
+.. code-block:: python
- from PySide6 import QtCore
+ from PySide6 import QtCore
- class MyOldStyleObject:
- pass
+ class MyOldStyleObject:
+ pass
- class MyObject(QtCore, MyOldStyleObject):
- pass
+ class MyObject(QtCore, MyOldStyleObject):
+ pass
this example will raise a 'TypeError' due to the limitation on PySide, to fix
this you will need use the new style class:
- .. code-block:: python
+.. code-block:: python
- from PySide6 import QtCore
+ from PySide6 import QtCore
- class MyOldStyleObject(object):
- pass
+ class MyOldStyleObject(object):
+ pass
- class MyObject(QtCore, MyOldStyleObject):
- pass
+ class MyObject(QtCore, MyOldStyleObject):
+ pass
All classes used for multiple inheritance with other PySide types need to have
diff --git a/sources/shiboken6/doc/examples/index.rst b/sources/shiboken6/doc/examples/index.rst
index 92a64195e..e3575bc06 100644
--- a/sources/shiboken6/doc/examples/index.rst
+++ b/sources/shiboken6/doc/examples/index.rst
@@ -4,6 +4,20 @@ Examples
C++ examples
------------
-.. toctree::
+.. grid:: 1 4 4 4
+ :gutter: 2
- samplebinding.rst
+ .. grid-item-card:: Sample Binding
+ :class-item: cover-img
+ :link: ../../examples/example_samplebinding_samplebinding.html
+ :img-top: ../images/icecream.png
+
+ .. grid-item-card:: Scriptable Application
+ :class-item: cover-img
+ :link: ../../examples/example_scriptableapplication_scriptableapplication.html
+ :img-top: ../../../_images/example_no_image.png
+
+ .. grid-item-card:: Widget Binding
+ :class-item: cover-img
+ :link: ../../examples/example_widgetbinding_widgetbinding.html
+ :img-top: ../../../_images/example_no_image.png
diff --git a/sources/shiboken6/doc/examples/samplebinding.rst b/sources/shiboken6/doc/examples/samplebinding.rst
deleted file mode 100644
index 17a5bd38f..000000000
--- a/sources/shiboken6/doc/examples/samplebinding.rst
+++ /dev/null
@@ -1,246 +0,0 @@
-SampleBinding Example
-***********************
-
-This example showcases how you can use Shiboken to generate CPython-based
-binding code for a C++ library. The C++ library is called :code:`Universe`,
-with two classes: :code:`Icecream` and :code:`Truck`. Ice-creams are
-characterized by their flavor, and :code:`Truck` serves as a vehicle of
-:code:`Icecream` distribution for kids in a neighborhood.
-
-First, let's look at the definition of the two classes:
-
-.. code-block:: cpp
- :caption: icecream.h
-
- class Icecream
- {
- public:
- Icecream(const std::string &flavor);
- virtual Icecream *clone();
- virtual ~Icecream();
- virtual const std::string getFlavor();
-
- private:
- std::string m_flavor;
- };
-
-.. code-block:: cpp
- :caption: truck.h
-
- class Truck {
- public:
- Truck(bool leaveOnDestruction = false);
- Truck(const Truck &other);
- Truck& operator=(const Truck &other);
- ~Truck();
-
- void addIcecreamFlavor(Icecream *icecream);
- void printAvailableFlavors() const;
-
- bool deliver() const;
- void arrive() const;
- void leave() const;
-
- void setLeaveOnDestruction(bool value);
- void setArrivalMessage(const std::string &message);
-
- private:
- void clearFlavors();
-
- bool m_leaveOnDestruction = false;
- std::string m_arrivalMessage = "A new icecream truck has arrived!\n";
- std::vector m_flavors;
- };
-
-Here's a summary of what's included in the :code:`Universe` library:
-
-* The :code:`Icecream` polymorphic type, which is intended to be overridden.
-* The :code:`Icecream::getFlavor()` method returns the flavor depending on the
- actual derived type.
-* The :code:`Truck` value type that contains pointers, hence the copy
- constructor.
-* :code:`Truck` stores the :code:`Icecream` objects in a vector, which can be
- modified via :code:`Truck::addIcecreamFlavor()`.
-* The :code:`Truck’s` arrival message can be customized using its
- :code:`setArrivalMessage()` method.
-* The :code:`Truck::deliver()` method tells us if the ice-cream delivery was
- successful.
-
-Shiboken typesystem
-====================
-
-Now that the library definitions are in place, the Shiboken generator needs a
-header file that includes the types we are interested in:
-
-.. code-block:: cpp
- :caption: bindings.h
-
- #ifndef BINDINGS_H
- #define BINDINGS_H
- #include "icecream.h"
- #include "truck.h"
- #endif // BINDINGS_H
-
-In addition, Shiboken also requires an XML-based typesystem file that defines the
-relationship between C++ and Python types:
-
-.. code-block:: xml
- :caption: bindings.xml
-
- <?xml version="1.0"?>
- <typesystem package="Universe">
- <primitive-type name="bool"/>
- <primitive-type name="std::string"/>
- <object-type name="Icecream">
- <modify-function signature="clone()">
- <modify-argument index="0">
- <define-ownership owner="c++"/>
- </modify-argument>
- </modify-function>
- </object-type>
- <value-type name="Truck">
- <modify-function signature="addIcecreamFlavor(Icecream*)">
- <modify-argument index="1">
- <define-ownership owner="c++"/>
- </modify-argument>
- </modify-function>
- </value-type>
- </typesystem>
-
-One important thing to notice here is that we declare :code:`"bool"` and
-:code:`"std::string"` as primitive types. These types are used by some of the
-C++ methods as parameters or return types, so Shiboken must know about them.
-Then, Shiboken can generate relevant conversion code between C++ and Python, although
-most C++ primitive types are handled by Shiboken without additional code.
-
-Next, we declare the two aforementioned classes. One of them as an
-“object-type” and the other as a “value-type”. The main difference is that
-object-types are passed around in generated code as pointers, whereas
-value-types are copied (value semantics).
-
-By specifying the names of these classes in the typesystem file, Shiboken
-automatically tries to generate bindings for all methods of those
-classes. You need not mention all the methods manually in the XML file, unless
-you want to modify them.
-
-Object ownership rules
-=======================
-
-Shiboken doesn't know if Python or C++ are responsible for freeing the C++ objects that were
-allocated in the Python code, and assuming this might lead to errors.
-There can be cases where Python should release the C++ memory when the reference count of the
-Python object becomes zero, but it should never delete the underlying C++ object just from
-assuming that it will not be deleted by underlying C++ library, or if it's maybe parented to
-another object (like QWidgets).
-
-In our case, the :code:`clone()` method is only called inside the C++ library,
-and we assume that the C++ code takes care of releasing the cloned object.
-
-As for :code:`addIcecreamFlavor()`, we know that a :code:`Truck` owns the
-:code:`Icecream` object, and will remove it once the :code:`Truck` is
-destroyed. That's why the ownership is set to “c++” in the typesystem file,
-so that the C++ objects are not deleted when the corresponding Python names
-go out of scope.
-
-Build
-=====
-
-To build the :code:`Universe` custom library and then generate bindings for it,
-use the :file:`CMakeLists.txt` file provided with the example. Later, you can reuse
-the file for your own libraries with minor changes.
-
-Now, run the :command:`"cmake ."` command from the prompt to configure the
-project and build with the toolchain of your choice; we recommend the
-‘(N)Makefiles’ generator.
-
-As a result, you end up with two shared libraries:
-:file:`libuniverse.(so/dylib/dll)` and :file:`Universe.(so/pyd)`. The former is
-the custom C++ library, and the latter is the Python module to import in your
-Python script.
-
-For more details about these platforms, see the :file:`README.md` file.
-
-Use the Python module
-=====================
-
-The following script uses the :code:`Universe` module, derives a few types from
-:code:`Icecream`, implements virtual methods, instantiates objects, and much more:
-
-.. code-block:: python
- :caption: main.py
-
- from Universe import Icecream, Truck
-
- class VanillaChocolateIcecream(Icecream):
- def __init__(self, flavor=""):
- super(VanillaChocolateIcecream, self).__init__(flavor)
-
- def clone(self):
- return VanillaChocolateIcecream(self.getFlavor())
-
- def getFlavor(self):
- return "vanilla sprinked with chocolate"
-
- class VanillaChocolateCherryIcecream(VanillaChocolateIcecream):
- def __init__(self, flavor=""):
- super(VanillaChocolateIcecream, self).__init__(flavor)
-
- def clone(self):
- return VanillaChocolateCherryIcecream(self.getFlavor())
-
- def getFlavor(self):
- base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor()
- return base_flavor + " and a cherry"
-
- if __name__ == '__main__':
- leave_on_destruction = True
- truck = Truck(leave_on_destruction)
-
- flavors = ["vanilla", "chocolate", "strawberry"]
- for f in flavors:
- icecream = Icecream(f)
- truck.addIcecreamFlavor(icecream)
-
- truck.addIcecreamFlavor(VanillaChocolateIcecream())
- truck.addIcecreamFlavor(VanillaChocolateCherryIcecream())
-
- truck.arrive()
- truck.printAvailableFlavors()
- result = truck.deliver()
-
- if result:
- print("All the kids got some icecream!")
- else:
- print("Aww, someone didn't get the flavor they wanted...")
-
- if not result:
- special_truck = Truck(truck)
- del truck
-
- print("")
- special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n")
- special_truck.arrive()
- special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream"))
- special_truck.printAvailableFlavors()
- special_truck.deliver()
- print("Now everyone got the flavor they wanted!")
- special_truck.leave()
-
-After importing the classes from the :code:`Universe` module, it derives two
-types from :code:`Icecream` for different “flavors”. It then creates a
-:code:`truck` to deliver some regular flavored Icecreams and two special ones.
-
-If the delivery fails, a new :code:`truck` is created with the old flavors
-copied over, and a new *magical* flavor that will surely satisfy all customers.
-
-Try running it to see if the ice creams are delivered.
-
-.. note::
- You can find the sources for this example under
- :file:`<PYTHON_ENV_ROOT>/site-packages/lib/PySide6/examples/samplebinding`.
-
-Refer to the following topics for detailed information about using Shiboken:
- * :doc:`Type System Variables <../typesystem_variables>`
- * :doc:`User Defined Type Conversion <../typesystem_converters>`
- * :doc:`Object ownership <../typesystem_ownership>`
- * :doc:`Considerations and Frequently Asked Questions <../considerations>`
diff --git a/sources/shiboken6/doc/gettingstarted.rst b/sources/shiboken6/doc/gettingstarted.rst
index b9a119615..cad49086d 100644
--- a/sources/shiboken6/doc/gettingstarted.rst
+++ b/sources/shiboken6/doc/gettingstarted.rst
@@ -11,11 +11,11 @@ need to continue if you already have a built PySide.
General Requirements
^^^^^^^^^^^^^^^^^^^^
- * **Python**: 3.6+
- * **Qt:** 6.0+
- * **libclang:** The libclang library, recommended: version 10 for 6.0+.
- Prebuilt versions of it can be `downloaded here`_.
- * **CMake:** 3.1+ is needed.
+* **Python**: 3.7+
+* **Qt:** 6.0+
+* **libclang:** The libclang library, recommended: version 10 for 6.0+.
+ Prebuilt versions of it can be `downloaded here`_.
+* **CMake:** 3.1+ is needed.
.. _downloaded here: https://download.qt.io/development_releases/prebuilt/libclang/
@@ -40,7 +40,7 @@ The same can be used for the module, changing the value of ``internal-build-type
``shiboken6-module``.
.. warning:: If you are planning to use PySide too, for examples like
- 'scriptableapplication' you need to have build it as well. The main issue is
+ 'scriptableapplication' you need to have build it as well. The main issue is
that your PySide and Shiboken needs to be build using the same dependencies
from Qt and libclang.
diff --git a/sources/shiboken6/doc/images/boostgen.png b/sources/shiboken6/doc/images/boostgen.png
deleted file mode 100644
index ae9d9fc3d..000000000
--- a/sources/shiboken6/doc/images/boostgen.png
+++ /dev/null
Binary files differ
diff --git a/sources/shiboken6/doc/images/converter.png b/sources/shiboken6/doc/images/converter.png
index cd52e2769..3935fdc60 100644
--- a/sources/shiboken6/doc/images/converter.png
+++ b/sources/shiboken6/doc/images/converter.png
Binary files differ
diff --git a/sources/shiboken6/doc/images/converter.svg b/sources/shiboken6/doc/images/converter.svg
index 4305eb720..2df5c88e5 100644
--- a/sources/shiboken6/doc/images/converter.svg
+++ b/sources/shiboken6/doc/images/converter.svg
@@ -1,349 +1,2227 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ width="908.50861"
+ zoomAndPan="magnify"
+ viewBox="0 0 681.38145 434.11857"
+ height="578.82477"
+ preserveAspectRatio="xMidYMid"
+ version="1.0"
+ id="svg5080"
+ sodipodi:docname="converter.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="206.375mm"
- height="100.54167mm"
- viewBox="0 0 206.375 100.54167"
- version="1.1"
- id="svg8"
- inkscape:version="0.92.2 2405546, 2018-03-11"
- sodipodi:docname="converter.svg">
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview5082"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="0.80648148"
+ inkscape:cx="413.52468"
+ inkscape:cy="205.2124"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg5080" />
<defs
- id="defs2">
- <marker
- inkscape:isstock="true"
- style="overflow:visible"
- id="marker1623"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend">
+ id="defs4108">
+ <g
+ id="g4028" />
+ <clipPath
+ id="24985ca8b2">
+ <path
+ d="m 325.10547,297.75 h 159.75 V 405 h -159.75 z m 0,0"
+ clip-rule="nonzero"
+ id="path4030" />
+ </clipPath>
+ <clipPath
+ id="3cea3902db">
+ <path
+ d="m 382.58984,359.24609 h 18 v 11.25 h -18 z m 0,0"
+ clip-rule="nonzero"
+ id="path4033" />
+ </clipPath>
+ <clipPath
+ id="dfab995897">
+ <path
+ d="m 325.10547,473.32031 h 159.75 v 107.25 h -159.75 z m 0,0"
+ clip-rule="nonzero"
+ id="path4036" />
+ </clipPath>
+ <clipPath
+ id="2d1327caba">
+ <path
+ d="m 411.91016,534.82031 h 18 v 11.25 h -18 z m 0,0"
+ clip-rule="nonzero"
+ id="path4039" />
+ </clipPath>
+ <clipPath
+ id="f03e985e13">
+ <path
+ d="m 113,313.11719 h 113.76172 v 76.5 H 113 Z m 0,0"
+ clip-rule="nonzero"
+ id="path4042" />
+ </clipPath>
+ <clipPath
+ id="c71ef1b2fa">
+ <path
+ d="m 112.76172,313.11719 h 114 v 76.5 h -114 z m 0,0"
+ clip-rule="nonzero"
+ id="path4045" />
+ </clipPath>
+ <clipPath
+ id="3bddcdf684">
+ <path
+ d="m 593.35156,488.69141 h 114 v 76.5 h -114 z m 0,0"
+ clip-rule="nonzero"
+ id="path4048" />
+ </clipPath>
+ <clipPath
+ id="cd19a8dfa8">
+ <path
+ d="m 588,313.11719 h 113.98828 v 76.5 H 588 Z m 0,0"
+ clip-rule="nonzero"
+ id="path4051" />
+ </clipPath>
+ <clipPath
+ id="61b05d6a70">
+ <path
+ d="m 125,427 h 89.71094 v 60 H 125 Z m 0,0"
+ clip-rule="nonzero"
+ id="path4054" />
+ </clipPath>
+ <clipPath
+ id="ea42d02648">
+ <path
+ d="m 124.77344,426.82031 h 89.9375 v 60.35547 h -89.9375 z m 0,0"
+ clip-rule="nonzero"
+ id="path4057" />
+ </clipPath>
+ <clipPath
+ id="84bd6662f0">
+ <path
+ d="m 125,497 h 89.71094 v 60 H 125 Z m 0,0"
+ clip-rule="nonzero"
+ id="path4060" />
+ </clipPath>
+ <clipPath
+ id="728d290ff8">
+ <path
+ d="m 124.77344,496.94922 h 89.9375 v 60.35547 h -89.9375 z m 0,0"
+ clip-rule="nonzero"
+ id="path4063" />
+ </clipPath>
+ <clipPath
+ id="00b091b271">
<path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path1621"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="marker1569"
- style="overflow:visible"
- inkscape:isstock="true"
- inkscape:collect="always">
+ d="m 125,567 h 89.71094 v 60 H 125 Z m 0,0"
+ clip-rule="nonzero"
+ id="path4066" />
+ </clipPath>
+ <clipPath
+ id="be13ebcaaa">
<path
- id="path1567"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:isstock="true"
- style="overflow:visible"
- id="marker1521"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:collect="always">
+ d="m 124.77344,566.78125 h 89.9375 v 60.35156 h -89.9375 z m 0,0"
+ clip-rule="nonzero"
+ id="path4069" />
+ </clipPath>
+ <clipPath
+ id="12ef88673f">
<path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path1519"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="marker1479"
- style="overflow:visible"
- inkscape:isstock="true"
- inkscape:collect="always">
+ d="m 242.54687,336.47266 h 66 v 30 h -66 z m 0,0"
+ clip-rule="nonzero"
+ id="path4072" />
+ </clipPath>
+ <clipPath
+ id="4425bd08fe">
<path
- id="path1477"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:isstock="true"
- style="overflow:visible"
- id="marker1443"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:collect="always">
+ d="m 503.92969,336.47266 h 66 v 30 h -66 z m 0,0"
+ clip-rule="nonzero"
+ id="path4075" />
+ </clipPath>
+ <clipPath
+ id="29f410bb45">
<path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path1441"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Lend"
- style="overflow:visible"
- inkscape:isstock="true"
- inkscape:collect="always">
+ d="m 503.92969,512.04297 h 66 v 30 h -66 z m 0,0"
+ clip-rule="nonzero"
+ id="path4078" />
+ </clipPath>
+ <clipPath
+ id="8612924f50">
<path
- id="path1154"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- inkscape:connector-curvature="0" />
- </marker>
+ d="m 236.54297,511.73437 h 66 v 30 h -66 z m 0,0"
+ clip-rule="nonzero"
+ id="path4081" />
+ </clipPath>
+ <clipPath
+ id="9616827f5c">
+ <path
+ d="m 238,451 h 62 v 38 h -62 z m 0,0"
+ clip-rule="nonzero"
+ id="path4084" />
+ </clipPath>
+ <clipPath
+ id="6d6215aef9">
+ <path
+ d="m 246.00781,440.04297 59.81641,27.89453 -12.67969,27.1875 -59.81641,-27.89063 z m 0,0"
+ clip-rule="nonzero"
+ id="path4087" />
+ </clipPath>
+ <clipPath
+ id="506e24dd3d">
+ <path
+ d="m 246.00781,440.04297 59.81641,27.89453 -12.67969,27.1875 -59.81641,-27.89063 z m 0,0"
+ clip-rule="nonzero"
+ id="path4090" />
+ </clipPath>
+ <clipPath
+ id="85c10bb5f0">
+ <path
+ d="m 246.00781,440.04297 59.81641,27.89453 -12.67969,27.1875 -59.81641,-27.89063 z m 0,0"
+ clip-rule="nonzero"
+ id="path4093" />
+ </clipPath>
+ <clipPath
+ id="96382ab88a">
+ <path
+ d="m 238,565 h 62 v 38 h -62 z m 0,0"
+ clip-rule="nonzero"
+ id="path4096" />
+ </clipPath>
+ <clipPath
+ id="8ee2f579d3">
+ <path
+ d="m 233.26953,586.86719 59.81641,-27.89063 12.67578,27.1875 -59.81641,27.89453 z m 0,0"
+ clip-rule="nonzero"
+ id="path4099" />
+ </clipPath>
+ <clipPath
+ id="c24345751d">
+ <path
+ d="m 246.00781,614.18359 59.81641,-27.89062 -12.67969,-27.19141 -59.81641,27.89453 z m 0,0"
+ clip-rule="nonzero"
+ id="path4102" />
+ </clipPath>
+ <clipPath
+ id="6c1dc82097">
+ <path
+ d="m 246.00781,614.18359 59.81641,-27.89062 -12.67969,-27.19141 -59.81641,27.89453 z m 0,0"
+ clip-rule="nonzero"
+ id="path4105" />
+ </clipPath>
</defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="382.16184"
- inkscape:cy="-28.417621"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- showgrid="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="0"
- inkscape:window-width="1002"
- inkscape:window-height="1042"
- inkscape:window-x="10"
- inkscape:window-y="28"
- inkscape:window-maximized="0">
- <inkscape:grid
- type="xygrid"
- id="grid971"
- originx="-58.208333"
- originy="-68.791657" />
- </sodipodi:namedview>
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-58.208333,-127.66667)">
+ <rect
+ x="-1.4210855e-14"
+ width="681.38147"
+ fill="#ffffff"
+ y="-2.8421709e-14"
+ height="434.11859"
+ fill-opacity="1"
+ id="rect4110"
+ style="stroke-width:0.559543" />
+ <path
+ fill="#41cb51"
+ d="M 256.85164,139.32657 V 62.127352 c 0,-0.9336 0.0898,-1.85938 0.27344,-2.77344 0.17968,-0.91406 0.44922,-1.80078 0.80468,-2.66406 0.35547,-0.86328 0.79297,-1.67969 1.3086,-2.45703 0.51562,-0.77344 1.10547,-1.49219 1.76172,-2.15235 0.65625,-0.66015 1.37109,-1.25 2.14453,-1.76562 0.77344,-0.51953 1.58984,-0.95703 2.44922,-1.3125 0.85937,-0.35938 1.74218,-0.62891 2.65625,-0.8086 0.91015,-0.18359 1.83203,-0.27343 2.76172,-0.27343 h 129.44531 c 0.92969,0 1.85156,0.0898 2.76172,0.27343 0.91406,0.17969 1.79687,0.44922 2.65625,0.8086 0.85937,0.35547 1.67578,0.79297 2.44922,1.3125 0.77343,0.51562 1.48828,1.10547 2.14453,1.76562 0.66015,0.66016 1.24609,1.37891 1.76172,2.15235 0.51562,0.77734 0.95312,1.59375 1.30859,2.45703 0.35547,0.86328 0.625,1.75 0.80469,2.66406 0.18359,0.91406 0.27343,1.83984 0.27343,2.77344 v 77.199218 c 0,0.93359 -0.0898,1.85937 -0.27343,2.77343 -0.17969,0.91407 -0.44922,1.80469 -0.80469,2.66407 -0.35547,0.86328 -0.79297,1.68359 -1.30859,2.45703 -0.51563,0.77734 -1.10157,1.49218 -1.76172,2.15234 -0.65625,0.66016 -1.3711,1.25 -2.14453,1.76953 -0.77344,0.51563 -1.58985,0.95313 -2.44922,1.3125 -0.85938,0.35547 -1.74219,0.625 -2.65625,0.8086 -0.91016,0.17968 -1.83203,0.27343 -2.76172,0.27343 H 271.0118 c -0.92969,0 -1.85157,-0.0937 -2.76172,-0.27343 -0.91407,-0.1836 -1.79688,-0.45313 -2.65625,-0.8086 -0.85938,-0.35937 -1.67578,-0.79687 -2.44922,-1.3125 -0.77344,-0.51953 -1.48828,-1.10937 -2.14453,-1.76953 -0.65625,-0.66016 -1.2461,-1.375 -1.76172,-2.15234 -0.51563,-0.77344 -0.95313,-1.59375 -1.3086,-2.45703 -0.35546,-0.85938 -0.625,-1.75 -0.80468,-2.66407 -0.1836,-0.91406 -0.27344,-1.83984 -0.27344,-2.77343 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4116" />
+ <g
+ clip-path="url(#24985ca8b2)"
+ id="g4120"
+ transform="translate(-69.242111,-250.64609)">
+ <path
+ fill="#41cb51"
+ d="m 484.67187,312.77344 v 77.19922 c 0,0.98437 -0.0937,1.96093 -0.28515,2.92968 -0.19531,0.96875 -0.47656,1.90625 -0.85547,2.82032 -0.375,0.91015 -0.83594,1.77734 -1.38281,2.59765 -0.54688,0.82031 -1.16797,1.57813 -1.86328,2.27735 -0.69532,0.69531 -1.44922,1.32031 -2.26954,1.86718 -0.8164,0.55078 -1.67968,1.01172 -2.58984,1.39063 -0.90625,0.375 -1.84375,0.66015 -2.80859,0.85547 -0.96485,0.1914 -1.9375,0.28906 -2.92188,0.28906 h -129.4375 c -0.98437,0 -1.95703,-0.0977 -2.92187,-0.28906 -0.96485,-0.19532 -1.90235,-0.48047 -2.8086,-0.85547 -0.91015,-0.37891 -1.77343,-0.83985 -2.58984,-1.39063 -0.82031,-0.54687 -1.57422,-1.17187 -2.26953,-1.86718 -0.69531,-0.69922 -1.31641,-1.45704 -1.86328,-2.27735 -0.54688,-0.82031 -1.00782,-1.6875 -1.38282,-2.59765 -0.3789,-0.91407 -0.66015,-1.85157 -0.85546,-2.82032 -0.19141,-0.96875 -0.28516,-1.94531 -0.28516,-2.92968 v -77.19922 c 0,-0.98828 0.0937,-1.96485 0.28516,-2.9336 0.19531,-0.96484 0.47656,-1.90625 0.85546,-2.8164 0.375,-0.91407 0.83594,-1.77735 1.38282,-2.59766 0.54687,-0.82422 1.16797,-1.58203 1.86328,-2.27734 0.69531,-0.69922 1.44922,-1.32422 2.26953,-1.8711 0.81641,-0.54687 1.67969,-1.01172 2.58984,-1.38672 0.90625,-0.3789 1.84375,-0.66406 2.8086,-0.85546 0.96484,-0.19532 1.9375,-0.28907 2.92187,-0.28907 h 129.44141 c 0.98437,0 1.95703,0.0977 2.92187,0.28907 0.96485,0.1914 1.90235,0.47656 2.8086,0.85546 0.91015,0.37891 1.76953,0.83985 2.58984,1.38672 0.81641,0.55078 1.57422,1.17188 2.26953,1.8711 0.69531,0.69531 1.3125,1.45703 1.85938,2.27734 0.54687,0.82031 1.00781,1.68359 1.38281,2.59766 0.37891,0.91015 0.66406,1.85156 0.85547,2.8164 0.1914,0.96875 0.28515,1.94532 0.28515,2.9336 z m -157.76171,77.19922 c 0,0.8789 0.082,1.75 0.2539,2.61328 0.17188,0.85937 0.42578,1.69922 0.76172,2.51172 0.33594,0.8125 0.74609,1.58203 1.23047,2.3164 0.48828,0.73047 1.04297,1.40625 1.66016,2.02735 0.62109,0.62109 1.29687,1.17968 2.02343,1.66796 0.73047,0.48829 1.5,0.89844 2.3086,1.23438 0.80859,0.33984 1.64453,0.59375 2.5039,0.76562 0.85938,0.17188 1.72657,0.25391 2.60547,0.25391 h 129.44141 c 0.875,0 1.74609,-0.082 2.60547,-0.25391 0.85937,-0.17187 1.69531,-0.42578 2.5039,-0.76562 0.8086,-0.33594 1.57813,-0.74609 2.3086,-1.23438 0.72656,-0.48828 1.40234,-1.04687 2.01953,-1.66796 0.62109,-0.6211 1.17578,-1.29688 1.66015,-2.02735 0.48829,-0.73437 0.89844,-1.5039 1.23438,-2.3164 0.33594,-0.8125 0.58984,-1.65235 0.76172,-2.51172 0.16797,-0.86328 0.2539,-1.73438 0.2539,-2.61328 v -77.19922 c 0,-0.87891 -0.0859,-1.75 -0.2539,-2.61328 -0.17188,-0.86329 -0.42578,-1.69922 -0.76172,-2.51172 -0.33594,-0.8125 -0.74609,-1.58594 -1.23438,-2.31641 -0.48437,-0.73047 -1.03906,-1.41016 -1.66015,-2.03125 -0.61719,-0.62109 -1.29297,-1.17578 -2.01953,-1.66406 -0.73047,-0.48828 -1.5,-0.90235 -2.3086,-1.23828 -0.80859,-0.33594 -1.64453,-0.58985 -2.5039,-0.76172 -0.85938,-0.17188 -1.73047,-0.25781 -2.60547,-0.25781 H 340.25781 c -0.8789,0 -1.74609,0.0859 -2.60547,0.25781 -0.85937,0.17187 -1.69531,0.42578 -2.5039,0.76172 -0.8086,0.33593 -1.57813,0.75 -2.3086,1.23828 -0.72656,0.48828 -1.40234,1.04297 -2.02343,1.66406 -0.61719,0.62109 -1.17188,1.30078 -1.66016,2.03125 -0.48438,0.73047 -0.89453,1.50391 -1.23047,2.31641 -0.33594,0.8125 -0.58984,1.64843 -0.76172,2.51172 -0.17187,0.86328 -0.2539,1.73437 -0.2539,2.61328 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4118" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4128"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(334.04375,371.84414)"
+ id="g4126">
+ <g
+ id="g4124">
+ <path
+ d="M 11.0625,-0.234375 C 9.550781,0.0664062 8.191406,0.21875 6.984375,0.21875 5.785156,0.21875 4.816406,0.0546875 4.078125,-0.265625 3.335938,-0.597656 2.765625,-1.113281 2.359375,-1.8125 1.960938,-2.507812 1.6875,-3.304688 1.53125,-4.203125 c -0.15625,-0.90625 -0.234375,-2.03125 -0.234375,-3.375 0,-1.351563 0.078125,-2.488281 0.234375,-3.40625 0.15625,-0.914063 0.429688,-1.722656 0.828125,-2.421875 0.40625,-0.707031 0.972656,-1.222656 1.703125,-1.546875 0.738281,-0.320313 1.691406,-0.484375 2.859375,-0.484375 1.175781,0 2.554687,0.164062 4.140625,0.484375 L 11,-13.53125 c -1.480469,-0.257812 -2.796875,-0.390625 -3.953125,-0.390625 -1.617187,0 -2.683594,0.480469 -3.203125,1.4375 -0.523438,0.960937 -0.78125,2.601563 -0.78125,4.921875 0,1.15625 0.046875,2.089844 0.140625,2.796875 0.09375,0.699219 0.28125,1.328125 0.5625,1.890625 0.28125,0.5625 0.6875,0.96875 1.21875,1.21875 0.53125,0.242188 1.3125,0.359375 2.34375,0.359375 1.039063,0 2.265625,-0.128906 3.671875,-0.390625 z m 0,0"
+ id="path4122" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4136"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(346.00962,371.84414)"
+ id="g4134">
+ <g
+ id="g4132">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4130" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4144"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(358.32742,371.84414)"
+ id="g4142">
+ <g
+ id="g4140">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4138" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4150"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(370.6414,371.84414)"
+ id="g4148">
+ <g
+ id="g4146" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4156"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(375.48053,371.84414)"
+ id="g4154">
+ <g
+ id="g4152" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4162"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(380.31967,371.84414)"
+ id="g4160">
+ <g
+ id="g4158" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4168"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(385.1588,371.84414)"
+ id="g4166">
+ <g
+ id="g4164" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4174"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(389.99794,371.84414)"
+ id="g4172">
+ <g
+ id="g4170" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4180"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(394.83707,371.84414)"
+ id="g4178">
+ <g
+ id="g4176" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4186"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(399.6762,371.84414)"
+ id="g4184">
+ <g
+ id="g4182" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4192"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(404.51534,371.84414)"
+ id="g4190">
+ <g
+ id="g4188" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4200"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(409.34843,371.84414)"
+ id="g4198">
+ <g
+ id="g4196">
+ <path
+ d="M 7.4375,-5.125 H 3.5625 V 0 H 1.875 v -15.21875 h 5.5625 c 1.65625,0 2.878906,0.40625 3.671875,1.21875 0.789063,0.804688 1.1875,2.03125 1.1875,3.6875 0,3.460938 -1.621094,5.1875 -4.859375,5.1875 z m -3.875,-1.5 h 3.84375 c 2.101562,0 3.15625,-1.226562 3.15625,-3.6875 0,-1.175781 -0.25,-2.039062 -0.75,-2.59375 -0.5,-0.550781 -1.304688,-0.828125 -2.40625,-0.828125 H 3.5625 Z m 0,0"
+ id="path4194" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4208"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(422.39211,371.84414)"
+ id="g4206">
+ <g
+ id="g4204">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4202" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4216"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(433.01622,371.84414)"
+ id="g4214">
+ <g
+ id="g4212">
+ <path
+ d="m 7.28125,-9.5625 h -3.5 v 5.25 c 0,1.261719 0.085938,2.089844 0.265625,2.484375 0.1875,0.398437 0.628906,0.59375 1.328125,0.59375 l 1.953125,-0.125 L 7.4375,0 c -0.980469,0.15625 -1.730469,0.234375 -2.25,0.234375 -1.148438,0 -1.9375,-0.2734375 -2.375,-0.828125 -0.4375,-0.5625 -0.65625,-1.625 -0.65625,-3.1875 V -9.5625 H 0.59375 V -11 h 1.5625 v -3.359375 h 1.625 V -11 h 3.5 z m 0,0"
+ id="path4210" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4224"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(440.73684,371.84414)"
+ id="g4222">
+ <g
+ id="g4220">
+ <path
+ d="m 3.234375,0 h -1.65625 v -15.796875 h 1.65625 v 5.40625 c 1.175781,-0.550781 2.304687,-0.828125 3.390625,-0.828125 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 H 8.6875 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.929688,-9.460938 7.300781,-9.75 6.34375,-9.75 c -0.929688,0 -1.824219,0.171875 -2.6875,0.515625 L 3.234375,-9.09375 Z m 0,0"
+ id="path4218" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4232"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(452.54873,371.84414)"
+ id="g4230">
+ <g
+ id="g4228">
+ <path
+ d="m 1.09375,-5.515625 c 0,-2.007813 0.359375,-3.460937 1.078125,-4.359375 0.71875,-0.894531 1.929687,-1.34375 3.640625,-1.34375 1.707031,0 2.914062,0.449219 3.625,1.34375 0.71875,0.898438 1.078125,2.351562 1.078125,4.359375 0,2 -0.339844,3.460937 -1.015625,4.375 -0.679688,0.90625 -1.914062,1.359375 -3.703125,1.359375 -1.78125,0 -3.011719,-0.453125 -3.6875,-1.359375 -0.679687,-0.914063 -1.015625,-2.375 -1.015625,-4.375 z m 1.703125,-0.03125 c 0,1.605469 0.191406,2.730469 0.578125,3.375 0.382812,0.648437 1.195312,0.96875 2.4375,0.96875 1.238281,0 2.050781,-0.316406 2.4375,-0.953125 0.382812,-0.644531 0.578125,-1.773438 0.578125,-3.390625 0,-1.613281 -0.214844,-2.722656 -0.640625,-3.328125 -0.429688,-0.613281 -1.21875,-0.921875 -2.375,-0.921875 -1.148438,0 -1.9375,0.308594 -2.375,0.921875 -0.429688,0.605469 -0.640625,1.714844 -0.640625,3.328125 z m 0,0"
+ id="path4226" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4240"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(464.16266,371.84414)"
+ id="g4238">
+ <g
+ id="g4236">
+ <path
+ d="M 3.234375,0 H 1.578125 V -11 H 3.21875 v 0.765625 c 1.1875,-0.65625 2.320312,-0.984375 3.40625,-0.984375 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 h -1.625 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.960938,-9.460938 7.320312,-9.75 6.34375,-9.75 c -0.480469,0 -0.980469,0.074219 -1.5,0.21875 -0.523438,0.136719 -0.917969,0.273438 -1.1875,0.40625 l -0.421875,0.1875 z m 0,0"
+ id="path4234" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#3cea3902db)"
+ id="g4244"
+ transform="translate(-69.242111,-250.64609)">
+ <path
+ fill="#ffffff"
+ d="m 400.46484,364.71094 -7.35156,-5.36328 c -0.11328,-0.082 -0.25,-0.0899 -0.375,-0.0274 -0.0586,0.0312 -0.1875,0.125 -0.1875,0.32031 v 2.9375 c 0,0.17969 -0.14453,0.32813 -0.32031,0.32813 h -9.28516 c -0.17578,0 -0.32031,0.14844 -0.32031,0.33203 v 3.29688 c 0,0.18359 0.14453,0.33203 0.32031,0.33203 h 9.28516 c 0.17578,0 0.32031,0.14843 0.32031,0.32812 v 2.9375 c 0,0.19531 0.12891,0.28906 0.1875,0.32031 0.125,0.0664 0.26172,0.0547 0.375,-0.0273 l 7.35156,-5.36328 c 0.0781,-0.0586 0.0859,-0.14063 0.0859,-0.17578 0,-0.0352 -0.008,-0.11719 -0.0859,-0.17578"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4242" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4252"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(358.72771,337.8254)"
+ id="g4250">
+ <g
+ id="g4248">
+ <path
+ d="m 6.796875,0.234375 c -2.199219,0 -3.695313,-0.601563 -4.484375,-1.8125 -0.78125,-1.21875 -1.171875,-3.21875 -1.171875,-6 0,-2.789063 0.394531,-4.773437 1.1875,-5.953125 0.789063,-1.1875 2.28125,-1.78125 4.46875,-1.78125 1.300781,0 2.738281,0.183594 4.3125,0.546875 l -0.09375,1.984375 c -1.3125,-0.238281 -2.632813,-0.359375 -3.953125,-0.359375 -1.324219,0 -2.21875,0.398437 -2.6875,1.1875 -0.46875,0.78125 -0.703125,2.257813 -0.703125,4.421875 0,2.15625 0.222656,3.632812 0.671875,4.421875 0.457031,0.78125 1.347656,1.171875 2.671875,1.171875 1.320313,0 2.65625,-0.109375 4,-0.328125 l 0.07813,2.03125 c -1.511719,0.3125 -2.945312,0.46875 -4.296875,0.46875 z m 0,0"
+ id="path4246" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4260"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(370.69358,337.8254)"
+ id="g4258">
+ <g
+ id="g4256">
+ <path
+ d="m 2.046875,-9.796875 c 0.757813,-0.957031 2.019531,-1.4375 3.78125,-1.4375 1.757813,0 3.015625,0.480469 3.765625,1.4375 0.757812,0.949219 1.140625,2.375 1.140625,4.28125 0,1.90625 -0.371094,3.34375 -1.109375,4.3125 -0.730469,0.960937 -1.996094,1.4375 -3.796875,1.4375 -1.804687,0 -3.074219,-0.476563 -3.8125,-1.4375 -0.730469,-0.96875 -1.09375,-2.40625 -1.09375,-4.3125 0,-1.90625 0.375,-3.332031 1.125,-4.28125 z M 3.84375,-2.65625 c 0.34375,0.585938 1.003906,0.875 1.984375,0.875 0.976563,0 1.632813,-0.289062 1.96875,-0.875 C 8.140625,-3.25 8.3125,-4.210938 8.3125,-5.546875 c 0,-1.332031 -0.183594,-2.273437 -0.546875,-2.828125 -0.355469,-0.5625 -1,-0.84375 -1.9375,-0.84375 -0.9375,0 -1.589844,0.28125 -1.953125,0.84375 -0.355469,0.554688 -0.53125,1.496094 -0.53125,2.828125 0,1.335937 0.164062,2.296875 0.5,2.890625 z m 0,0"
+ id="path4254" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4268"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(382.3515,337.8254)"
+ id="g4266">
+ <g
+ id="g4264">
+ <path
+ d="M 3.84375,0 H 1.453125 v -11 h 2.375 v 0.6875 c 1.070313,-0.613281 2.082031,-0.921875 3.03125,-0.921875 1.46875,0 2.46875,0.417969 3,1.25 0.539063,0.824219 0.8125,2.1875 0.8125,4.09375 V 0 h -2.375 v -5.828125 c 0,-1.1875 -0.132813,-2.03125 -0.390625,-2.53125 -0.25,-0.5 -0.773438,-0.75 -1.5625,-0.75 -0.75,0 -1.46875,0.148437 -2.15625,0.4375 L 3.84375,-8.53125 Z m 0,0"
+ id="path4262" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4276"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(394.36136,337.8254)"
+ id="g4274">
+ <g
+ id="g4272">
+ <path
+ d="m 0.421875,-11 h 2.5 L 5.03125,-2.046875 H 5.734375 L 7.9375,-11 h 2.453125 L 7.53125,0 H 3.25 Z m 0,0"
+ id="path4270" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4284"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(405.16143,337.8254)"
+ id="g4282">
+ <g
+ id="g4280">
+ <path
+ d="m 9.28125,-1.984375 0.625,-0.0625 0.03125,1.78125 c -1.667969,0.3320312 -3.148438,0.5 -4.4375,0.5 -1.625,0 -2.796875,-0.441406 -3.515625,-1.328125 -0.710937,-0.894531 -1.0625,-2.328125 -1.0625,-4.296875 0,-3.894531 1.59375,-5.84375 4.78125,-5.84375 3.070313,0 4.609375,1.679687 4.609375,5.03125 l -0.15625,1.71875 h -6.8125 c 0.00781,0.90625 0.207031,1.574219 0.59375,2 0.382812,0.429687 1.097656,0.640625 2.140625,0.640625 1.039063,0 2.109375,-0.046875 3.203125,-0.140625 z M 7.96875,-6.34375 c 0,-1.082031 -0.171875,-1.835938 -0.515625,-2.265625 -0.34375,-0.4375 -0.929687,-0.65625 -1.75,-0.65625 -0.824219,0 -1.421875,0.230469 -1.796875,0.6875 -0.375,0.460937 -0.570312,1.203125 -0.578125,2.234375 z m 0,0"
+ id="path4278" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4292"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(416.33545,337.8254)"
+ id="g4290">
+ <g
+ id="g4288">
+ <path
+ d="m 1.453125,0 v -11 h 2.375 v 1.3125 c 1.25,-0.800781 2.492187,-1.316406 3.734375,-1.546875 v 2.390625 c -1.261719,0.25 -2.339844,0.574219 -3.234375,0.96875 L 3.84375,-7.671875 V 0 Z m 0,0"
+ id="path4286" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4300"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(424.27603,337.8254)"
+ id="g4298">
+ <g
+ id="g4296">
+ <path
+ d="M 7.375,-8.953125 H 4.328125 v 4.84375 c 0,0.898437 0.066406,1.492187 0.203125,1.78125 0.132812,0.292969 0.472656,0.4375 1.015625,0.4375 l 1.796875,-0.0625 0.109375,1.90625 c -0.980469,0.1875 -1.726563,0.28125 -2.234375,0.28125 -1.25,0 -2.109375,-0.28125 -2.578125,-0.84375 -0.460937,-0.570313 -0.6875,-1.648437 -0.6875,-3.234375 V -8.953125 H 0.546875 V -11 h 1.40625 v -3.1875 h 2.375 V -11 H 7.375 Z m 0,0"
+ id="path4294" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4308"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(432.15063,337.8254)"
+ id="g4306">
+ <g
+ id="g4304">
+ <path
+ d="m 9.28125,-1.984375 0.625,-0.0625 0.03125,1.78125 c -1.667969,0.3320312 -3.148438,0.5 -4.4375,0.5 -1.625,0 -2.796875,-0.441406 -3.515625,-1.328125 -0.710937,-0.894531 -1.0625,-2.328125 -1.0625,-4.296875 0,-3.894531 1.59375,-5.84375 4.78125,-5.84375 3.070313,0 4.609375,1.679687 4.609375,5.03125 l -0.15625,1.71875 h -6.8125 c 0.00781,0.90625 0.207031,1.574219 0.59375,2 0.382812,0.429687 1.097656,0.640625 2.140625,0.640625 1.039063,0 2.109375,-0.046875 3.203125,-0.140625 z M 7.96875,-6.34375 c 0,-1.082031 -0.171875,-1.835938 -0.515625,-2.265625 -0.34375,-0.4375 -0.929687,-0.65625 -1.75,-0.65625 -0.824219,0 -1.421875,0.230469 -1.796875,0.6875 -0.375,0.460937 -0.570312,1.203125 -0.578125,2.234375 z m 0,0"
+ id="path4302" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4316"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(443.32464,337.8254)"
+ id="g4314">
+ <g
+ id="g4312">
+ <path
+ d="m 1.453125,0 v -11 h 2.375 v 1.3125 c 1.25,-0.800781 2.492187,-1.316406 3.734375,-1.546875 v 2.390625 c -1.261719,0.25 -2.339844,0.574219 -3.234375,0.96875 L 3.84375,-7.671875 V 0 Z m 0,0"
+ id="path4310" />
+ </g>
+ </g>
+ </g>
+ <path
+ fill="#41cb51"
+ d="m 256.85164,314.90078 v -77.19921 c 0,-0.9336 0.0898,-1.85938 0.27344,-2.77344 0.17968,-0.91406 0.44922,-1.80469 0.80468,-2.66406 0.35547,-0.86329 0.79297,-1.6836 1.3086,-2.45704 0.51562,-0.77734 1.10547,-1.49218 1.76172,-2.15234 0.65625,-0.66016 1.37109,-1.25 2.14453,-1.76953 0.77344,-0.51563 1.58984,-0.95313 2.44922,-1.3125 0.85937,-0.35547 1.74218,-0.625 2.65625,-0.80859 0.91015,-0.17969 1.83203,-0.27344 2.76172,-0.27344 h 129.44531 c 0.92969,0 1.85156,0.0937 2.76172,0.27344 0.91406,0.18359 1.79687,0.45312 2.65625,0.80859 0.85937,0.35937 1.67578,0.79687 2.44922,1.3125 0.77343,0.51953 1.48828,1.10937 2.14453,1.76953 0.66015,0.66016 1.24609,1.375 1.76172,2.15234 0.51562,0.77344 0.95312,1.59375 1.30859,2.45704 0.35547,0.85937 0.625,1.75 0.80469,2.66406 0.18359,0.91406 0.27343,1.83984 0.27343,2.77344 v 77.19921 c 0,0.9336 -0.0898,1.85938 -0.27343,2.77344 -0.17969,0.91406 -0.44922,1.80078 -0.80469,2.66406 -0.35547,0.86329 -0.79297,1.67969 -1.30859,2.45704 -0.51563,0.77343 -1.10157,1.49218 -1.76172,2.15234 -0.65625,0.66016 -1.3711,1.25 -2.14453,1.76562 -0.77344,0.51954 -1.58985,0.95704 -2.44922,1.3125 -0.85938,0.35938 -1.74219,0.62891 -2.65625,0.8086 -0.91016,0.18359 -1.83203,0.27344 -2.76172,0.27344 H 271.0118 c -0.92969,0 -1.85157,-0.0899 -2.76172,-0.27344 -0.91407,-0.17969 -1.79688,-0.44922 -2.65625,-0.8086 -0.85938,-0.35546 -1.67578,-0.79296 -2.44922,-1.3125 -0.77344,-0.51562 -1.48828,-1.10546 -2.14453,-1.76562 -0.65625,-0.66016 -1.2461,-1.37891 -1.76172,-2.15234 -0.51563,-0.77735 -0.95313,-1.59375 -1.3086,-2.45704 -0.35546,-0.86328 -0.625,-1.75 -0.80468,-2.66406 -0.1836,-0.91406 -0.27344,-1.83984 -0.27344,-2.77344 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4318" />
+ <g
+ clip-path="url(#dfab995897)"
+ id="g4322"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#17a81a;fill-opacity:1;stroke:none;stroke-width:0.82824755;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 127,132.95834 0.0687,26.45833 h 63.43127 l 5.29167,-5.29167 v -26.45833 h -63.5 z"
- id="path3715-5-6-7-9-8-7"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
+ fill="#41cb51"
+ d="m 484.67187,488.34766 v 77.19531 c 0,0.98828 -0.0937,1.96484 -0.28515,2.93359 -0.19531,0.96875 -0.47656,1.90625 -0.85547,2.82031 -0.375,0.91016 -0.83594,1.77735 -1.38281,2.59766 -0.54688,0.82031 -1.16797,1.57813 -1.86328,2.27734 -0.69532,0.69532 -1.44922,1.32032 -2.26954,1.86719 -0.8164,0.54688 -1.67968,1.01172 -2.58984,1.39063 -0.90625,0.375 -1.84375,0.66015 -2.80859,0.85156 -0.96485,0.19531 -1.9375,0.28906 -2.92188,0.28906 h -129.4375 c -0.98437,0 -1.95703,-0.0937 -2.92187,-0.28906 -0.96485,-0.19141 -1.90235,-0.47656 -2.8086,-0.85156 -0.91015,-0.37891 -1.77343,-0.84375 -2.58984,-1.39063 -0.82031,-0.54687 -1.57422,-1.17187 -2.26953,-1.86719 -0.69531,-0.69921 -1.31641,-1.45703 -1.86328,-2.27734 -0.54688,-0.82031 -1.00782,-1.6875 -1.38282,-2.59766 -0.3789,-0.91406 -0.66015,-1.85156 -0.85546,-2.82031 -0.19141,-0.96875 -0.28516,-1.94531 -0.28516,-2.93359 v -77.19531 c 0,-0.98829 0.0937,-1.96485 0.28516,-2.9336 0.19531,-0.96875 0.47656,-1.90625 0.85546,-2.82031 0.375,-0.91016 0.83594,-1.77734 1.38282,-2.59766 0.54687,-0.82031 1.16797,-1.57812 1.86328,-2.27734 0.69531,-0.69531 1.44922,-1.32031 2.26953,-1.86719 0.81641,-0.54687 1.67969,-1.01172 2.58984,-1.39062 0.90625,-0.375 1.84375,-0.66016 2.8086,-0.85547 0.96484,-0.19141 1.9375,-0.28516 2.92187,-0.28516 h 129.44141 c 0.98437,0 1.95703,0.0937 2.92187,0.28906 0.96485,0.19141 1.90235,0.47657 2.8086,0.85547 0.91015,0.375 1.76953,0.83985 2.58984,1.38672 0.81641,0.55078 1.57422,1.17188 2.26953,1.8711 0.69531,0.69531 1.3125,1.45703 1.85938,2.27734 0.54687,0.82031 1.00781,1.68359 1.38281,2.59766 0.37891,0.91015 0.66406,1.84765 0.85547,2.8164 0.1914,0.96875 0.28515,1.94531 0.28515,2.9336 z m -157.76171,77.19531 c 0,0.88281 0.082,1.7539 0.2539,2.61328 0.17188,0.86328 0.42578,1.70312 0.76172,2.51562 0.33594,0.8125 0.74609,1.58204 1.23047,2.3125 0.48828,0.73438 1.04297,1.41016 1.66016,2.03125 0.62109,0.6211 1.29687,1.17579 2.02343,1.66407 0.73047,0.48828 1.5,0.90234 2.3086,1.23828 0.80859,0.33594 1.64453,0.58984 2.5039,0.76172 0.85938,0.17187 1.72657,0.25781 2.60547,0.25781 h 129.44141 c 0.875,0 1.74609,-0.0859 2.60547,-0.25781 0.85937,-0.17188 1.69531,-0.42578 2.5039,-0.76172 0.8086,-0.33594 1.57813,-0.75 2.3086,-1.23828 0.72656,-0.48828 1.40234,-1.04297 2.01953,-1.66407 0.62109,-0.62109 1.17578,-1.29687 1.66015,-2.03125 0.48829,-0.73046 0.89844,-1.5 1.23438,-2.3125 0.33594,-0.8125 0.58984,-1.65234 0.76172,-2.51562 0.16797,-0.85938 0.2539,-1.73047 0.2539,-2.61328 v -77.19531 c 0,-0.88282 -0.0859,-1.75391 -0.2539,-2.61329 -0.17188,-0.86328 -0.42578,-1.70312 -0.76172,-2.51562 -0.33594,-0.8125 -0.74609,-1.58203 -1.23438,-2.3125 -0.48437,-0.73438 -1.03906,-1.41016 -1.66015,-2.03125 -0.61719,-0.62109 -1.29297,-1.17578 -2.01953,-1.66406 -0.73047,-0.48828 -1.5,-0.90235 -2.3086,-1.23828 -0.80859,-0.33594 -1.64453,-0.58985 -2.5039,-0.76172 -0.85938,-0.17188 -1.73047,-0.25782 -2.60547,-0.25782 H 340.25781 c -0.8789,0 -1.74609,0.0859 -2.60547,0.25782 -0.85937,0.17187 -1.69531,0.42578 -2.5039,0.76172 -0.8086,0.33593 -1.57813,0.75 -2.3086,1.23828 -0.72656,0.48828 -1.40234,1.04297 -2.02343,1.66406 -0.61719,0.62109 -1.17188,1.29687 -1.66016,2.03125 -0.48438,0.73047 -0.89453,1.5 -1.23047,2.3125 -0.33594,0.8125 -0.58984,1.65234 -0.76172,2.51562 -0.17187,0.85938 -0.2539,1.73047 -0.2539,2.61329 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4320" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4330"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(336.46249,547.41743)"
+ id="g4328">
+ <g
+ id="g4326">
+ <path
+ d="M 7.4375,-5.125 H 3.5625 V 0 H 1.875 v -15.21875 h 5.5625 c 1.65625,0 2.878906,0.40625 3.671875,1.21875 0.789063,0.804688 1.1875,2.03125 1.1875,3.6875 0,3.460938 -1.621094,5.1875 -4.859375,5.1875 z m -3.875,-1.5 h 3.84375 c 2.101562,0 3.15625,-1.226562 3.15625,-3.6875 0,-1.175781 -0.25,-2.039062 -0.75,-2.59375 -0.5,-0.550781 -1.304688,-0.828125 -2.40625,-0.828125 H 3.5625 Z m 0,0"
+ id="path4324" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4338"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(349.50617,547.41743)"
+ id="g4336">
+ <g
+ id="g4334">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4332" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4346"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(360.13028,547.41743)"
+ id="g4344">
+ <g
+ id="g4342">
+ <path
+ d="m 7.28125,-9.5625 h -3.5 v 5.25 c 0,1.261719 0.085938,2.089844 0.265625,2.484375 0.1875,0.398437 0.628906,0.59375 1.328125,0.59375 l 1.953125,-0.125 L 7.4375,0 c -0.980469,0.15625 -1.730469,0.234375 -2.25,0.234375 -1.148438,0 -1.9375,-0.2734375 -2.375,-0.828125 -0.4375,-0.5625 -0.65625,-1.625 -0.65625,-3.1875 V -9.5625 H 0.59375 V -11 h 1.5625 v -3.359375 h 1.625 V -11 h 3.5 z m 0,0"
+ id="path4340" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4354"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(367.8509,547.41743)"
+ id="g4352">
+ <g
+ id="g4350">
+ <path
+ d="m 3.234375,0 h -1.65625 v -15.796875 h 1.65625 v 5.40625 c 1.175781,-0.550781 2.304687,-0.828125 3.390625,-0.828125 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 H 8.6875 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.929688,-9.460938 7.300781,-9.75 6.34375,-9.75 c -0.929688,0 -1.824219,0.171875 -2.6875,0.515625 L 3.234375,-9.09375 Z m 0,0"
+ id="path4348" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4362"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(379.6628,547.41743)"
+ id="g4360">
+ <g
+ id="g4358">
+ <path
+ d="m 1.09375,-5.515625 c 0,-2.007813 0.359375,-3.460937 1.078125,-4.359375 0.71875,-0.894531 1.929687,-1.34375 3.640625,-1.34375 1.707031,0 2.914062,0.449219 3.625,1.34375 0.71875,0.898438 1.078125,2.351562 1.078125,4.359375 0,2 -0.339844,3.460937 -1.015625,4.375 -0.679688,0.90625 -1.914062,1.359375 -3.703125,1.359375 -1.78125,0 -3.011719,-0.453125 -3.6875,-1.359375 -0.679687,-0.914063 -1.015625,-2.375 -1.015625,-4.375 z m 1.703125,-0.03125 c 0,1.605469 0.191406,2.730469 0.578125,3.375 0.382812,0.648437 1.195312,0.96875 2.4375,0.96875 1.238281,0 2.050781,-0.316406 2.4375,-0.953125 0.382812,-0.644531 0.578125,-1.773438 0.578125,-3.390625 0,-1.613281 -0.214844,-2.722656 -0.640625,-3.328125 -0.429688,-0.613281 -1.21875,-0.921875 -2.375,-0.921875 -1.148438,0 -1.9375,0.308594 -2.375,0.921875 -0.429688,0.605469 -0.640625,1.714844 -0.640625,3.328125 z m 0,0"
+ id="path4356" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4370"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(391.27673,547.41743)"
+ id="g4368">
+ <g
+ id="g4366">
+ <path
+ d="M 3.234375,0 H 1.578125 V -11 H 3.21875 v 0.765625 c 1.1875,-0.65625 2.320312,-0.984375 3.40625,-0.984375 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 h -1.625 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.960938,-9.460938 7.320312,-9.75 6.34375,-9.75 c -0.480469,0 -0.980469,0.074219 -1.5,0.21875 -0.523438,0.136719 -0.917969,0.273438 -1.1875,0.40625 l -0.421875,0.1875 z m 0,0"
+ id="path4364" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4376"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(403.08359,547.41743)"
+ id="g4374">
+ <g
+ id="g4372" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4382"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(407.92272,547.41743)"
+ id="g4380">
+ <g
+ id="g4378" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4388"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(412.76185,547.41743)"
+ id="g4386">
+ <g
+ id="g4384" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4394"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(417.60099,547.41743)"
+ id="g4392">
+ <g
+ id="g4390" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4400"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(422.44012,547.41743)"
+ id="g4398">
+ <g
+ id="g4396" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4406"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(427.27926,547.41743)"
+ id="g4404">
+ <g
+ id="g4402" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4412"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(432.11839,547.41743)"
+ id="g4410">
+ <g
+ id="g4408" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4420"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(436.95077,547.41743)"
+ id="g4418">
+ <g
+ id="g4416">
+ <path
+ d="M 11.0625,-0.234375 C 9.550781,0.0664062 8.191406,0.21875 6.984375,0.21875 5.785156,0.21875 4.816406,0.0546875 4.078125,-0.265625 3.335938,-0.597656 2.765625,-1.113281 2.359375,-1.8125 1.960938,-2.507812 1.6875,-3.304688 1.53125,-4.203125 c -0.15625,-0.90625 -0.234375,-2.03125 -0.234375,-3.375 0,-1.351563 0.078125,-2.488281 0.234375,-3.40625 0.15625,-0.914063 0.429688,-1.722656 0.828125,-2.421875 0.40625,-0.707031 0.972656,-1.222656 1.703125,-1.546875 0.738281,-0.320313 1.691406,-0.484375 2.859375,-0.484375 1.175781,0 2.554687,0.164062 4.140625,0.484375 L 11,-13.53125 c -1.480469,-0.257812 -2.796875,-0.390625 -3.953125,-0.390625 -1.617187,0 -2.683594,0.480469 -3.203125,1.4375 -0.523438,0.960937 -0.78125,2.601563 -0.78125,4.921875 0,1.15625 0.046875,2.089844 0.140625,2.796875 0.09375,0.699219 0.28125,1.328125 0.5625,1.890625 0.28125,0.5625 0.6875,0.96875 1.21875,1.21875 0.53125,0.242188 1.3125,0.359375 2.34375,0.359375 1.039063,0 2.265625,-0.128906 3.671875,-0.390625 z m 0,0"
+ id="path4414" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4428"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(448.91665,547.41743)"
+ id="g4426">
+ <g
+ id="g4424">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4422" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4436"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(461.23445,547.41743)"
+ id="g4434">
+ <g
+ id="g4432">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4430" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#2d1327caba)"
+ id="g4440"
+ transform="translate(-69.242111,-250.64609)">
+ <path
+ fill="#ffffff"
+ d="m 429.78516,540.28516 -7.35157,-5.36329 c -0.10937,-0.082 -0.25,-0.0937 -0.375,-0.0273 -0.0547,0.0312 -0.1875,0.125 -0.1875,0.32031 v 2.9375 c 0,0.17969 -0.14453,0.32813 -0.32031,0.32813 h -9.28516 c -0.17578,0 -0.32031,0.14844 -0.32031,0.32812 v 3.30078 c 0,0.1836 0.14453,0.33204 0.32031,0.33204 h 9.28516 c 0.17578,0 0.32031,0.14453 0.32031,0.32812 v 2.9375 c 0,0.19531 0.13282,0.28906 0.1875,0.32031 0.125,0.0625 0.26563,0.0547 0.375,-0.0273 l 7.35157,-5.36328 c 0.0781,-0.0586 0.0898,-0.14453 0.0898,-0.17578 0,-0.0352 -0.0117,-0.11719 -0.0898,-0.17578"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4438" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4448"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(358.72771,513.39871)"
+ id="g4446">
+ <g
+ id="g4444">
+ <path
+ d="m 6.796875,0.234375 c -2.199219,0 -3.695313,-0.601563 -4.484375,-1.8125 -0.78125,-1.21875 -1.171875,-3.21875 -1.171875,-6 0,-2.789063 0.394531,-4.773437 1.1875,-5.953125 0.789063,-1.1875 2.28125,-1.78125 4.46875,-1.78125 1.300781,0 2.738281,0.183594 4.3125,0.546875 l -0.09375,1.984375 c -1.3125,-0.238281 -2.632813,-0.359375 -3.953125,-0.359375 -1.324219,0 -2.21875,0.398437 -2.6875,1.1875 -0.46875,0.78125 -0.703125,2.257813 -0.703125,4.421875 0,2.15625 0.222656,3.632812 0.671875,4.421875 0.457031,0.78125 1.347656,1.171875 2.671875,1.171875 1.320313,0 2.65625,-0.109375 4,-0.328125 l 0.07813,2.03125 c -1.511719,0.3125 -2.945312,0.46875 -4.296875,0.46875 z m 0,0"
+ id="path4442" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4456"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(370.69358,513.39871)"
+ id="g4454">
+ <g
+ id="g4452">
+ <path
+ d="m 2.046875,-9.796875 c 0.757813,-0.957031 2.019531,-1.4375 3.78125,-1.4375 1.757813,0 3.015625,0.480469 3.765625,1.4375 0.757812,0.949219 1.140625,2.375 1.140625,4.28125 0,1.90625 -0.371094,3.34375 -1.109375,4.3125 -0.730469,0.960937 -1.996094,1.4375 -3.796875,1.4375 -1.804687,0 -3.074219,-0.476563 -3.8125,-1.4375 -0.730469,-0.96875 -1.09375,-2.40625 -1.09375,-4.3125 0,-1.90625 0.375,-3.332031 1.125,-4.28125 z M 3.84375,-2.65625 c 0.34375,0.585938 1.003906,0.875 1.984375,0.875 0.976563,0 1.632813,-0.289062 1.96875,-0.875 C 8.140625,-3.25 8.3125,-4.210938 8.3125,-5.546875 c 0,-1.332031 -0.183594,-2.273437 -0.546875,-2.828125 -0.355469,-0.5625 -1,-0.84375 -1.9375,-0.84375 -0.9375,0 -1.589844,0.28125 -1.953125,0.84375 -0.355469,0.554688 -0.53125,1.496094 -0.53125,2.828125 0,1.335937 0.164062,2.296875 0.5,2.890625 z m 0,0"
+ id="path4450" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4464"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(382.3515,513.39871)"
+ id="g4462">
+ <g
+ id="g4460">
+ <path
+ d="M 3.84375,0 H 1.453125 v -11 h 2.375 v 0.6875 c 1.070313,-0.613281 2.082031,-0.921875 3.03125,-0.921875 1.46875,0 2.46875,0.417969 3,1.25 0.539063,0.824219 0.8125,2.1875 0.8125,4.09375 V 0 h -2.375 v -5.828125 c 0,-1.1875 -0.132813,-2.03125 -0.390625,-2.53125 -0.25,-0.5 -0.773438,-0.75 -1.5625,-0.75 -0.75,0 -1.46875,0.148437 -2.15625,0.4375 L 3.84375,-8.53125 Z m 0,0"
+ id="path4458" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4472"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(394.36136,513.39871)"
+ id="g4470">
+ <g
+ id="g4468">
+ <path
+ d="m 0.421875,-11 h 2.5 L 5.03125,-2.046875 H 5.734375 L 7.9375,-11 h 2.453125 L 7.53125,0 H 3.25 Z m 0,0"
+ id="path4466" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4480"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(405.16143,513.39871)"
+ id="g4478">
+ <g
+ id="g4476">
+ <path
+ d="m 9.28125,-1.984375 0.625,-0.0625 0.03125,1.78125 c -1.667969,0.3320312 -3.148438,0.5 -4.4375,0.5 -1.625,0 -2.796875,-0.441406 -3.515625,-1.328125 -0.710937,-0.894531 -1.0625,-2.328125 -1.0625,-4.296875 0,-3.894531 1.59375,-5.84375 4.78125,-5.84375 3.070313,0 4.609375,1.679687 4.609375,5.03125 l -0.15625,1.71875 h -6.8125 c 0.00781,0.90625 0.207031,1.574219 0.59375,2 0.382812,0.429687 1.097656,0.640625 2.140625,0.640625 1.039063,0 2.109375,-0.046875 3.203125,-0.140625 z M 7.96875,-6.34375 c 0,-1.082031 -0.171875,-1.835938 -0.515625,-2.265625 -0.34375,-0.4375 -0.929687,-0.65625 -1.75,-0.65625 -0.824219,0 -1.421875,0.230469 -1.796875,0.6875 -0.375,0.460937 -0.570312,1.203125 -0.578125,2.234375 z m 0,0"
+ id="path4474" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4488"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(416.33545,513.39871)"
+ id="g4486">
+ <g
+ id="g4484">
+ <path
+ d="m 1.453125,0 v -11 h 2.375 v 1.3125 c 1.25,-0.800781 2.492187,-1.316406 3.734375,-1.546875 v 2.390625 c -1.261719,0.25 -2.339844,0.574219 -3.234375,0.96875 L 3.84375,-7.671875 V 0 Z m 0,0"
+ id="path4482" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4496"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(424.27603,513.39871)"
+ id="g4494">
+ <g
+ id="g4492">
+ <path
+ d="M 7.375,-8.953125 H 4.328125 v 4.84375 c 0,0.898437 0.066406,1.492187 0.203125,1.78125 0.132812,0.292969 0.472656,0.4375 1.015625,0.4375 l 1.796875,-0.0625 0.109375,1.90625 c -0.980469,0.1875 -1.726563,0.28125 -2.234375,0.28125 -1.25,0 -2.109375,-0.28125 -2.578125,-0.84375 -0.460937,-0.570313 -0.6875,-1.648437 -0.6875,-3.234375 V -8.953125 H 0.546875 V -11 h 1.40625 v -3.1875 h 2.375 V -11 H 7.375 Z m 0,0"
+ id="path4490" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4504"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(432.15063,513.39871)"
+ id="g4502">
+ <g
+ id="g4500">
+ <path
+ d="m 9.28125,-1.984375 0.625,-0.0625 0.03125,1.78125 c -1.667969,0.3320312 -3.148438,0.5 -4.4375,0.5 -1.625,0 -2.796875,-0.441406 -3.515625,-1.328125 -0.710937,-0.894531 -1.0625,-2.328125 -1.0625,-4.296875 0,-3.894531 1.59375,-5.84375 4.78125,-5.84375 3.070313,0 4.609375,1.679687 4.609375,5.03125 l -0.15625,1.71875 h -6.8125 c 0.00781,0.90625 0.207031,1.574219 0.59375,2 0.382812,0.429687 1.097656,0.640625 2.140625,0.640625 1.039063,0 2.109375,-0.046875 3.203125,-0.140625 z M 7.96875,-6.34375 c 0,-1.082031 -0.171875,-1.835938 -0.515625,-2.265625 -0.34375,-0.4375 -0.929687,-0.65625 -1.75,-0.65625 -0.824219,0 -1.421875,0.230469 -1.796875,0.6875 -0.375,0.460937 -0.570312,1.203125 -0.578125,2.234375 z m 0,0"
+ id="path4498" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4512"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(443.32464,513.39871)"
+ id="g4510">
+ <g
+ id="g4508">
+ <path
+ d="m 1.453125,0 v -11 h 2.375 v 1.3125 c 1.25,-0.800781 2.492187,-1.316406 3.734375,-1.546875 v 2.390625 c -1.261719,0.25 -2.339844,0.574219 -3.234375,0.96875 L 3.84375,-7.671875 V 0 Z m 0,0"
+ id="path4506" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#f03e985e13)"
+ id="g4516"
+ transform="translate(-69.242111,-250.64609)">
+ <path
+ fill="#09102b"
+ d="m 113.46875,378.90234 v -55.07031 c 0,-0.66406 0.0625,-1.32422 0.19141,-1.97656 0.13281,-0.65235 0.32422,-1.28516 0.57812,-1.89844 0.25391,-0.61719 0.5625,-1.19922 0.9336,-1.75391 0.36718,-0.55468 0.78515,-1.0664 1.2539,-1.53515 0.46875,-0.46875 0.98047,-0.89063 1.53125,-1.26172 0.55469,-0.36719 1.13672,-0.67969 1.75,-0.93359 0.60938,-0.25782 1.24219,-0.44922 1.89453,-0.57813 0.64844,-0.12891 1.3086,-0.19531 1.96875,-0.19531 h 92.375 c 0.66016,0 1.32031,0.0664 1.96875,0.19531 0.65235,0.12891 1.28516,0.32031 1.89453,0.57813 0.61328,0.2539 1.19532,0.5664 1.75,0.93359 0.55078,0.37109 1.0625,0.79297 1.53125,1.26172 0.46875,0.46875 0.88672,0.98047 1.25391,1.53515 0.37109,0.55469 0.67969,1.13672 0.93359,1.75391 0.25391,0.61328 0.44532,1.24609 0.57813,1.89844 0.1289,0.65234 0.1914,1.3125 0.1914,1.97656 v 55.07031 c 0,0.66407 -0.0625,1.32422 -0.1914,1.97657 -0.13281,0.65234 -0.32422,1.28515 -0.57813,1.89843 -0.2539,0.61719 -0.5625,1.19922 -0.93359,1.75391 -0.36719,0.55469 -0.78516,1.06641 -1.25391,1.53516 -0.46875,0.46875 -0.98047,0.89062 -1.53125,1.26171 -0.55468,0.36719 -1.13672,0.67969 -1.75,0.9336 -0.60937,0.25781 -1.24218,0.44922 -1.89453,0.57812 -0.64844,0.12891 -1.30859,0.19532 -1.96875,0.19532 h -92.375 c -0.66015,0 -1.32031,-0.0664 -1.96875,-0.19532 -0.65234,-0.1289 -1.28515,-0.32031 -1.89453,-0.57812 -0.61328,-0.25391 -1.19531,-0.56641 -1.75,-0.9336 -0.55078,-0.37109 -1.0625,-0.79296 -1.53125,-1.26171 -0.46875,-0.46875 -0.88672,-0.98047 -1.2539,-1.53516 -0.3711,-0.55469 -0.67969,-1.13672 -0.9336,-1.75391 -0.2539,-0.61328 -0.44531,-1.24609 -0.57812,-1.89843 -0.12891,-0.65235 -0.19141,-1.3125 -0.19141,-1.97657 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4514" />
+ </g>
+ <g
+ clip-path="url(#c71ef1b2fa)"
+ id="g4520"
+ transform="translate(-69.242111,-250.64609)">
+ <path
+ fill="#09102b"
+ d="m 226.62891,323.83203 v 55.06641 c 0,0.70312 -0.0703,1.40234 -0.20704,2.08984 -0.13671,0.69141 -0.33984,1.36328 -0.60546,2.01172 -0.26954,0.65234 -0.59766,1.26953 -0.98829,1.85156 -0.39062,0.58594 -0.83203,1.12891 -1.32812,1.625 -0.49609,0.5 -1.03906,0.94141 -1.62109,1.33594 -0.58204,0.39062 -1.19922,0.71875 -1.84766,0.98828 -0.64844,0.26953 -1.31641,0.47266 -2.00391,0.60938 -0.6875,0.13671 -1.38281,0.20703 -2.08593,0.20703 h -92.36719 c -0.70313,0 -1.39844,-0.0703 -2.08594,-0.20703 -0.6875,-0.13672 -1.35547,-0.33985 -2.0039,-0.60938 -0.64844,-0.26953 -1.26563,-0.59766 -1.84766,-0.98828 -0.58203,-0.39453 -1.125,-0.83594 -1.62109,-1.33594 -0.4961,-0.49609 -0.9375,-1.03906 -1.32813,-1.625 -0.39062,-0.58203 -0.71875,-1.19922 -0.98828,-1.85156 -0.26563,-0.64844 -0.46875,-1.32031 -0.60547,-2.01172 -0.13672,-0.6875 -0.20703,-1.38672 -0.20703,-2.08984 v -55.06641 c 0,-0.70312 0.0703,-1.39844 0.20703,-2.08984 0.13672,-0.69141 0.33984,-1.35938 0.60547,-2.01172 0.26953,-0.64844 0.59766,-1.26563 0.98828,-1.85156 0.39063,-0.58594 0.83203,-1.125 1.32813,-1.625 0.49609,-0.4961 1.03906,-0.94141 1.62109,-1.33204 0.58203,-0.39062 1.19922,-0.72265 1.84766,-0.99218 0.64843,-0.26953 1.3164,-0.47266 2.0039,-0.60938 0.6875,-0.13672 1.38281,-0.20703 2.08594,-0.20703 h 92.37109 c 0.69922,0 1.39453,0.0703 2.08203,0.20703 0.6875,0.13672 1.35547,0.33985 2.00391,0.60938 0.64844,0.26953 1.26562,0.60156 1.84766,0.99218 0.58593,0.39063 1.125,0.83594 1.62109,1.33204 0.49609,0.5 0.9375,1.03906 1.32812,1.625 0.39063,0.58593 0.71875,1.20312 0.98829,1.85156 0.26562,0.65234 0.46875,1.32031 0.60546,2.01172 0.13672,0.6914 0.20704,1.38672 0.20704,2.08984 z m -112.58203,55.06641 c 0,0.6289 0.0625,1.25 0.18359,1.86328 0.125,0.61719 0.30469,1.21484 0.54297,1.79297 0.23828,0.57812 0.53125,1.1289 0.8789,1.65234 0.34766,0.51953 0.74219,1.00391 1.1875,1.44531 0.44141,0.44532 0.92188,0.83985 1.44141,1.19141 0.51953,0.34766 1.07031,0.64062 1.64844,0.88281 0.57812,0.23828 1.17187,0.41797 1.78515,0.54297 0.61329,0.12109 1.23438,0.18359 1.85938,0.18359 h 92.37109 c 0.625,0 1.24219,-0.0625 1.85547,-0.18359 0.61328,-0.125 1.21094,-0.30469 1.78906,-0.54297 0.57813,-0.24219 1.125,-0.53515 1.64453,-0.88281 0.52344,-0.35156 1.00391,-0.74609 1.44532,-1.19141 0.4414,-0.4414 0.83593,-0.92578 1.18359,-1.44531 0.34766,-0.52344 0.64063,-1.07422 0.88281,-1.65234 0.23828,-0.57813 0.41797,-1.17578 0.53907,-1.79297 0.125,-0.61328 0.18359,-1.23438 0.18359,-1.86328 v -55.06641 c 0,-0.625 -0.0586,-1.24609 -0.18359,-1.86328 -0.1211,-0.61328 -0.30079,-1.21094 -0.53907,-1.79297 -0.24218,-0.57812 -0.53515,-1.12891 -0.88281,-1.64844 -0.34766,-0.52343 -0.74219,-1.0039 -1.18359,-1.44922 -0.44141,-0.44531 -0.92188,-0.83984 -1.44532,-1.1875 -0.51953,-0.34765 -1.0664,-0.64453 -1.64453,-0.88281 -0.57812,-0.24219 -1.17578,-0.42187 -1.78906,-0.54297 -0.61328,-0.125 -1.23047,-0.18359 -1.85547,-0.18359 h -92.37109 c -0.625,0 -1.24609,0.0586 -1.85938,0.18359 -0.61328,0.1211 -1.20703,0.30078 -1.78515,0.54297 -0.57813,0.23828 -1.12891,0.53516 -1.64844,0.88281 -0.51953,0.34766 -1,0.74219 -1.44141,1.1875 -0.44531,0.44532 -0.83984,0.92579 -1.1875,1.44922 -0.34765,0.51953 -0.64062,1.07032 -0.8789,1.64844 -0.23828,0.58203 -0.41797,1.17969 -0.54297,1.79297 -0.12109,0.61719 -0.18359,1.23828 -0.18359,1.86328 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4518" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4528"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(126.50046,359.41913)"
+ id="g4526">
+ <g
+ id="g4524">
+ <path
+ d="M 11.0625,-0.234375 C 9.550781,0.0664062 8.191406,0.21875 6.984375,0.21875 5.785156,0.21875 4.816406,0.0546875 4.078125,-0.265625 3.335938,-0.597656 2.765625,-1.113281 2.359375,-1.8125 1.960938,-2.507812 1.6875,-3.304688 1.53125,-4.203125 c -0.15625,-0.90625 -0.234375,-2.03125 -0.234375,-3.375 0,-1.351563 0.078125,-2.488281 0.234375,-3.40625 0.15625,-0.914063 0.429688,-1.722656 0.828125,-2.421875 0.40625,-0.707031 0.972656,-1.222656 1.703125,-1.546875 0.738281,-0.320313 1.691406,-0.484375 2.859375,-0.484375 1.175781,0 2.554687,0.164062 4.140625,0.484375 L 11,-13.53125 c -1.480469,-0.257812 -2.796875,-0.390625 -3.953125,-0.390625 -1.617187,0 -2.683594,0.480469 -3.203125,1.4375 -0.523438,0.960937 -0.78125,2.601563 -0.78125,4.921875 0,1.15625 0.046875,2.089844 0.140625,2.796875 0.09375,0.699219 0.28125,1.328125 0.5625,1.890625 0.28125,0.5625 0.6875,0.96875 1.21875,1.21875 0.53125,0.242188 1.3125,0.359375 2.34375,0.359375 1.039063,0 2.265625,-0.128906 3.671875,-0.390625 z m 0,0"
+ id="path4522" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4536"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(138.46633,359.41913)"
+ id="g4534">
+ <g
+ id="g4532">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4530" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4544"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(150.78413,359.41913)"
+ id="g4542">
+ <g
+ id="g4540">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4538" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4550"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(163.10194,359.41913)"
+ id="g4548">
+ <g
+ id="g4546" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4558"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(167.94108,359.41913)"
+ id="g4556">
+ <g
+ id="g4554">
+ <path
+ d="m 0.28125,-13.703125 v -1.515625 h 11 v 1.515625 H 6.640625 V 0 H 4.96875 v -13.703125 z m 0,0"
+ id="path4552" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4566"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(179.51102,359.41913)"
+ id="g4564">
+ <g
+ id="g4562">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4560" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4574"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(190.13512,359.41913)"
+ id="g4572">
+ <g
+ id="g4570">
+ <path
+ d="M 1.578125,4.890625 V -11 H 3.21875 v 0.796875 c 1.113281,-0.675781 2.210938,-1.015625 3.296875,-1.015625 1.394531,0 2.40625,0.445312 3.03125,1.328125 C 10.179688,-9.003906 10.5,-7.539062 10.5,-5.5 c 0,2.042969 -0.375,3.507812 -1.125,4.390625 -0.742188,0.886719 -1.964844,1.328125 -3.671875,1.328125 -0.898437,0 -1.71875,-0.078125 -2.46875,-0.234375 v 4.90625 z M 6.265625,-9.75 c -0.4375,0 -0.914063,0.074219 -1.421875,0.21875 -0.5,0.148438 -0.898438,0.292969 -1.1875,0.4375 l -0.421875,0.234375 v 7.40625 c 1.039063,0.167969 1.832031,0.25 2.375,0.25 1.1875,0 2.019531,-0.335937 2.5,-1.015625 0.476563,-0.675781 0.71875,-1.773438 0.71875,-3.296875 0,-1.53125 -0.21875,-2.617187 -0.65625,-3.265625 C 7.742188,-9.425781 7.109375,-9.75 6.265625,-9.75 Z m 0,0"
+ id="path4568" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4582"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(201.72705,359.41913)"
+ id="g4580">
+ <g
+ id="g4578">
+ <path
+ d="M 9.0625,-1.359375 9.703125,-1.4375 9.75,-0.125 C 8.070312,0.101562 6.640625,0.21875 5.453125,0.21875 c -1.585937,0 -2.710937,-0.457031 -3.375,-1.375 C 1.421875,-2.070312 1.09375,-3.5 1.09375,-5.4375 c 0,-3.851562 1.535156,-5.78125 4.609375,-5.78125 1.476563,0 2.582031,0.417969 3.3125,1.25 0.738281,0.824219 1.109375,2.121094 1.109375,3.890625 L 10.03125,-4.8125 H 2.765625 c 0,1.21875 0.21875,2.121094 0.65625,2.703125 0.445313,0.585937 1.21875,0.875 2.3125,0.875 1.09375,0 2.203125,-0.039063 3.328125,-0.125 z m -0.59375,-4.78125 c 0,-1.34375 -0.21875,-2.289063 -0.65625,-2.84375 -0.429688,-0.5625 -1.132812,-0.84375 -2.109375,-0.84375 -0.96875,0 -1.703125,0.292969 -2.203125,0.875 -0.492188,0.585937 -0.742188,1.523437 -0.75,2.8125 z m 0,0"
+ id="path4576" />
+ </g>
+ </g>
+ </g>
+ <path
+ fill="#09102b"
+ d="m 524.81258,303.82657 v -55.06641 c 0,-0.66406 0.0664,-1.32422 0.19531,-1.97656 0.12891,-0.65235 0.32031,-1.28516 0.57422,-1.90235 0.2539,-0.61328 0.5664,-1.19531 0.93359,-1.75 0.3711,-0.55468 0.78906,-1.0664 1.25781,-1.53515 0.46875,-0.47266 0.98047,-0.89063 1.53125,-1.26172 0.55079,-0.3711 1.13282,-0.67969 1.7461,-0.9375 0.61328,-0.25391 1.24609,-0.44531 1.89453,-0.57422 0.65234,-0.12891 1.30859,-0.19531 1.97266,-0.19531 h 92.37109 c 0.66406,0 1.32031,0.0664 1.97266,0.19531 0.64843,0.12891 1.28125,0.32031 1.89453,0.57422 0.61328,0.25781 1.19531,0.5664 1.74609,0.9375 0.55469,0.37109 1.0625,0.78906 1.53125,1.26172 0.46875,0.46875 0.89063,0.98047 1.25781,1.53515 0.36719,0.55469 0.67969,1.13672 0.9336,1.75 0.2539,0.61719 0.44531,1.25 0.57422,1.90235 0.1289,0.65234 0.19531,1.3125 0.19531,1.97656 v 55.06641 c 0,0.66796 -0.0664,1.32421 -0.19531,1.97656 -0.12891,0.65625 -0.32032,1.28906 -0.57422,1.90234 -0.25391,0.61328 -0.56641,1.19922 -0.9336,1.75391 -0.36718,0.55078 -0.78906,1.0625 -1.25781,1.53515 -0.46875,0.46875 -0.97656,0.89063 -1.53125,1.25782 -0.55078,0.37109 -1.13281,0.68359 -1.74609,0.9375 -0.61328,0.2539 -1.2461,0.44922 -1.89453,0.57812 -0.65235,0.12891 -1.3086,0.19531 -1.97266,0.19531 h -92.37109 c -0.66407,0 -1.32032,-0.0664 -1.97266,-0.19531 -0.64844,-0.1289 -1.28125,-0.32422 -1.89453,-0.57812 -0.61328,-0.25391 -1.19531,-0.56641 -1.7461,-0.9375 -0.55078,-0.36719 -1.0625,-0.78907 -1.53125,-1.25782 -0.46875,-0.47265 -0.88671,-0.98437 -1.25781,-1.53515 -0.36719,-0.55469 -0.67969,-1.14063 -0.93359,-1.75391 -0.25391,-0.61328 -0.44531,-1.24609 -0.57422,-1.90234 -0.12891,-0.65235 -0.19531,-1.3086 -0.19531,-1.97656 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4584" />
+ <g
+ clip-path="url(#3bddcdf684)"
+ id="g4588"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#3a4055;fill-opacity:1;stroke:none;stroke-width:0.67261654;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 68.791667,132.95834 v 26.45833 H 105.83333 L 111.125,154.125 V 127.66667 H 74.083333 Z"
- id="path3715-5-6-7-9-8-7-6-3"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
+ fill="#09102b"
+ d="m 707.21875,499.40625 v 55.06641 c 0,0.70312 -0.0703,1.39843 -0.20703,2.08984 -0.13672,0.69141 -0.33985,1.35937 -0.60938,2.01172 -0.26562,0.64844 -0.59765,1.26562 -0.98828,1.85156 -0.38672,0.58594 -0.83203,1.12891 -1.32812,1.625 -0.4961,0.49609 -1.03516,0.94141 -1.61719,1.33203 -0.58594,0.39063 -1.19922,0.72266 -1.84766,0.99219 -0.64843,0.26953 -1.3164,0.47266 -2.00781,0.60937 -0.6875,0.13672 -1.38281,0.20704 -2.08203,0.20704 h -92.36719 c -0.70312,0 -1.39844,-0.0703 -2.08594,-0.20704 -0.6875,-0.13671 -1.35546,-0.33984 -2.0039,-0.60937 -0.64844,-0.26953 -1.26563,-0.60156 -1.84766,-0.99219 -0.58594,-0.39062 -1.125,-0.83594 -1.62109,-1.33203 -0.4961,-0.49609 -0.9375,-1.03906 -1.32813,-1.625 -0.39062,-0.58594 -0.71875,-1.20312 -0.98828,-1.85156 -0.26953,-0.65235 -0.47265,-1.32031 -0.60937,-2.01172 -0.13672,-0.69141 -0.20313,-1.38672 -0.20313,-2.08984 v -55.06641 c 0,-0.70313 0.0664,-1.39844 0.20313,-2.08984 0.13672,-0.69141 0.33984,-1.35938 0.60937,-2.01172 0.26953,-0.64844 0.59766,-1.26953 0.98828,-1.85157 0.39063,-0.58593 0.83203,-1.1289 1.32813,-1.625 0.49609,-0.5 1.03515,-0.9414 1.62109,-1.33203 0.58203,-0.39062 1.19922,-0.72265 1.84766,-0.99218 0.64844,-0.26954 1.3164,-0.47266 2.0039,-0.60938 0.6875,-0.13672 1.38282,-0.20703 2.08594,-0.20703 h 92.36719 c 0.70312,0 1.39844,0.0703 2.08594,0.20703 0.6875,0.13672 1.35547,0.33984 2.0039,0.60938 0.64844,0.26953 1.26563,0.60156 1.84766,0.99218 0.58203,0.39063 1.12109,0.83594 1.61719,1.33203 0.49609,0.4961 0.9414,1.03907 1.33203,1.625 0.38672,0.58594 0.71875,1.20313 0.98437,1.85157 0.26953,0.65234 0.47266,1.32031 0.60938,2.01172 0.13672,0.6914 0.20703,1.38671 0.20703,2.08984 z m -112.58203,55.06641 c 0,0.625 0.0625,1.24609 0.18359,1.86328 0.1211,0.61328 0.30078,1.21093 0.54297,1.79297 0.23828,0.57812 0.53125,1.1289 0.87891,1.65234 0.34765,0.51953 0.74218,1.00391 1.18359,1.44531 0.44531,0.44531 0.92578,0.83985 1.44531,1.1875 0.51953,0.35156 1.06641,0.64453 1.64453,0.88281 0.57813,0.24219 1.17579,0.42188 1.78907,0.54297 0.61328,0.125 1.23047,0.1836 1.85937,0.1836 h 92.36719 c 0.625,0 1.24609,-0.0586 1.85937,-0.1836 0.61329,-0.12109 1.20704,-0.30078 1.78516,-0.54297 0.57813,-0.23828 1.12891,-0.53125 1.64844,-0.88281 0.51953,-0.34765 1,-0.74219 1.44531,-1.1875 0.44141,-0.4414 0.83594,-0.92578 1.18359,-1.44531 0.34766,-0.52344 0.64063,-1.07422 0.87891,-1.65234 0.23828,-0.58204 0.42188,-1.17969 0.54297,-1.79297 0.12109,-0.61719 0.18359,-1.23828 0.18359,-1.86328 v -55.06641 c 0,-0.625 -0.0625,-1.24609 -0.18359,-1.86328 -0.12109,-0.61328 -0.30469,-1.21094 -0.54297,-1.79297 -0.23828,-0.57813 -0.53125,-1.12891 -0.87891,-1.65234 -0.34765,-0.51954 -0.74218,-1.00391 -1.18359,-1.44532 -0.44531,-0.44531 -0.92578,-0.83984 -1.44531,-1.1875 -0.51953,-0.35156 -1.07031,-0.64453 -1.64844,-0.88281 -0.57812,-0.24219 -1.17187,-0.42187 -1.78516,-0.54687 -0.61328,-0.1211 -1.23437,-0.1836 -1.85937,-0.1836 h -92.36719 c -0.6289,0 -1.24609,0.0625 -1.85937,0.1836 -0.61328,0.125 -1.21094,0.30468 -1.78907,0.54687 -0.57812,0.23828 -1.125,0.53125 -1.64453,0.88281 -0.51953,0.34766 -1,0.74219 -1.44531,1.1875 -0.44141,0.44141 -0.83594,0.92578 -1.18359,1.44532 -0.34766,0.52343 -0.64063,1.07421 -0.87891,1.65234 -0.24219,0.58203 -0.42187,1.17969 -0.54297,1.79297 -0.12109,0.61719 -0.18359,1.23828 -0.18359,1.86328 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4586" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4596"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(607.08883,534.99247)"
+ id="g4594">
+ <g
+ id="g4592">
+ <path
+ d="M 11.0625,-0.234375 C 9.550781,0.0664062 8.191406,0.21875 6.984375,0.21875 5.785156,0.21875 4.816406,0.0546875 4.078125,-0.265625 3.335938,-0.597656 2.765625,-1.113281 2.359375,-1.8125 1.960938,-2.507812 1.6875,-3.304688 1.53125,-4.203125 c -0.15625,-0.90625 -0.234375,-2.03125 -0.234375,-3.375 0,-1.351563 0.078125,-2.488281 0.234375,-3.40625 0.15625,-0.914063 0.429688,-1.722656 0.828125,-2.421875 0.40625,-0.707031 0.972656,-1.222656 1.703125,-1.546875 0.738281,-0.320313 1.691406,-0.484375 2.859375,-0.484375 1.175781,0 2.554687,0.164062 4.140625,0.484375 L 11,-13.53125 c -1.480469,-0.257812 -2.796875,-0.390625 -3.953125,-0.390625 -1.617187,0 -2.683594,0.480469 -3.203125,1.4375 -0.523438,0.960937 -0.78125,2.601563 -0.78125,4.921875 0,1.15625 0.046875,2.089844 0.140625,2.796875 0.09375,0.699219 0.28125,1.328125 0.5625,1.890625 0.28125,0.5625 0.6875,0.96875 1.21875,1.21875 0.53125,0.242188 1.3125,0.359375 2.34375,0.359375 1.039063,0 2.265625,-0.128906 3.671875,-0.390625 z m 0,0"
+ id="path4590" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4604"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(619.0547,534.99247)"
+ id="g4602">
+ <g
+ id="g4600">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4598" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4612"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(631.37251,534.99247)"
+ id="g4610">
+ <g
+ id="g4608">
+ <path
+ d="M 1.203125,-4.78125 V -6.265625 H 5.375 V -10.5625 h 1.53125 v 4.296875 h 4.203125 V -4.78125 H 6.90625 V -0.4375 H 5.375 v -4.34375 z m 0,0"
+ id="path4606" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4618"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(643.69031,534.99247)"
+ id="g4616">
+ <g
+ id="g4614" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4626"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(648.52945,534.99247)"
+ id="g4624">
+ <g
+ id="g4622">
+ <path
+ d="m 0.28125,-13.703125 v -1.515625 h 11 v 1.515625 H 6.640625 V 0 H 4.96875 v -13.703125 z m 0,0"
+ id="path4620" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4634"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(660.09939,534.99247)"
+ id="g4632">
+ <g
+ id="g4630">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4628" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4642"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(670.72349,534.99247)"
+ id="g4640">
+ <g
+ id="g4638">
+ <path
+ d="M 1.578125,4.890625 V -11 H 3.21875 v 0.796875 c 1.113281,-0.675781 2.210938,-1.015625 3.296875,-1.015625 1.394531,0 2.40625,0.445312 3.03125,1.328125 C 10.179688,-9.003906 10.5,-7.539062 10.5,-5.5 c 0,2.042969 -0.375,3.507812 -1.125,4.390625 -0.742188,0.886719 -1.964844,1.328125 -3.671875,1.328125 -0.898437,0 -1.71875,-0.078125 -2.46875,-0.234375 v 4.90625 z M 6.265625,-9.75 c -0.4375,0 -0.914063,0.074219 -1.421875,0.21875 -0.5,0.148438 -0.898438,0.292969 -1.1875,0.4375 l -0.421875,0.234375 v 7.40625 c 1.039063,0.167969 1.832031,0.25 2.375,0.25 1.1875,0 2.019531,-0.335937 2.5,-1.015625 0.476563,-0.675781 0.71875,-1.773438 0.71875,-3.296875 0,-1.53125 -0.21875,-2.617187 -0.65625,-3.265625 C 7.742188,-9.425781 7.109375,-9.75 6.265625,-9.75 Z m 0,0"
+ id="path4636" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4650"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(682.31543,534.99247)"
+ id="g4648">
+ <g
+ id="g4646">
+ <path
+ d="M 9.0625,-1.359375 9.703125,-1.4375 9.75,-0.125 C 8.070312,0.101562 6.640625,0.21875 5.453125,0.21875 c -1.585937,0 -2.710937,-0.457031 -3.375,-1.375 C 1.421875,-2.070312 1.09375,-3.5 1.09375,-5.4375 c 0,-3.851562 1.535156,-5.78125 4.609375,-5.78125 1.476563,0 2.582031,0.417969 3.3125,1.25 0.738281,0.824219 1.109375,2.121094 1.109375,3.890625 L 10.03125,-4.8125 H 2.765625 c 0,1.21875 0.21875,2.121094 0.65625,2.703125 0.445313,0.585937 1.21875,0.875 2.3125,0.875 1.09375,0 2.203125,-0.039063 3.328125,-0.125 z m -0.59375,-4.78125 c 0,-1.34375 -0.21875,-2.289063 -0.65625,-2.84375 -0.429688,-0.5625 -1.132812,-0.84375 -2.109375,-0.84375 -0.96875,0 -1.703125,0.292969 -2.203125,0.875 -0.492188,0.585937 -0.742188,1.523437 -0.75,2.8125 z m 0,0"
+ id="path4644" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#cd19a8dfa8)"
+ id="g4656"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#848895;fill-opacity:1;stroke:none;stroke-width:0.52087492;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 58.208333,173.96875 V 185.875 h 48.947917 l 3.96875,-3.96875 V 170 H 62.177083 Z"
- id="path3715-5-6-7-9-8-7-6-56"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
+ fill="#306998"
+ d="m 588.69141,378.90234 v -55.07031 c 0,-0.66406 0.0664,-1.32422 0.19531,-1.97656 0.1289,-0.65235 0.32031,-1.28516 0.57422,-1.89844 0.2539,-0.61719 0.5664,-1.19922 0.93359,-1.75391 0.37109,-0.55468 0.78906,-1.0664 1.25781,-1.53515 0.46875,-0.46875 0.98047,-0.89063 1.53125,-1.26172 0.55078,-0.36719 1.13282,-0.67969 1.7461,-0.93359 0.61328,-0.25782 1.24609,-0.44922 1.89843,-0.57813 0.64844,-0.12891 1.30469,-0.19531 1.96875,-0.19531 h 92.3711 c 0.66406,0 1.32031,0.0664 1.97265,0.19531 0.65235,0.12891 1.28125,0.32031 1.89454,0.57813 0.61328,0.2539 1.19531,0.5664 1.74609,0.93359 0.55469,0.37109 1.0625,0.79297 1.53125,1.26172 0.46875,0.46875 0.89062,0.98047 1.25781,1.53515 0.36719,0.55469 0.67969,1.13672 0.9336,1.75391 0.2539,0.61328 0.44531,1.24609 0.57421,1.89844 0.12891,0.65234 0.19532,1.3125 0.19532,1.97656 v 55.07031 c 0,0.66407 -0.0664,1.32422 -0.19532,1.97657 -0.1289,0.65234 -0.32031,1.28515 -0.57421,1.89843 -0.25391,0.61719 -0.56641,1.19922 -0.9336,1.75391 -0.36719,0.55469 -0.78906,1.06641 -1.25781,1.53516 -0.46875,0.46875 -0.97656,0.89062 -1.53125,1.26171 -0.55078,0.36719 -1.13281,0.67969 -1.74609,0.9336 -0.61329,0.25781 -1.24219,0.44922 -1.89454,0.57812 -0.65234,0.12891 -1.30859,0.19532 -1.97265,0.19532 h -92.3711 c -0.66406,0 -1.32031,-0.0664 -1.96875,-0.19532 -0.65234,-0.1289 -1.28515,-0.32031 -1.89843,-0.57812 -0.61328,-0.25391 -1.19532,-0.56641 -1.7461,-0.9336 -0.55078,-0.37109 -1.0625,-0.79296 -1.53125,-1.26171 -0.46875,-0.46875 -0.88672,-0.98047 -1.25781,-1.53516 -0.36719,-0.55469 -0.67969,-1.13672 -0.93359,-1.75391 -0.25391,-0.61328 -0.44532,-1.24609 -0.57422,-1.89843 -0.12891,-0.65235 -0.19531,-1.3125 -0.19531,-1.97657 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4652" />
<path
- style="fill:#17a81a;fill-opacity:1;stroke:none;stroke-width:0.82824755;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 127.00003,175.29167 0.0687,26.45833 H 190.5 l 5.29167,-5.29167 V 170 h -63.5 z"
- id="path3715-5-6-7-9-8-7-2"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
+ fill="#306998"
+ d="m 701.85547,323.83203 v 55.06641 c 0,0.70312 -0.0703,1.40234 -0.20703,2.08984 -0.13672,0.69141 -0.33985,1.36328 -0.60938,2.01172 -0.26562,0.65234 -0.59765,1.26953 -0.98437,1.85156 -0.39063,0.58594 -0.83594,1.12891 -1.33203,1.625 -0.4961,0.5 -1.03516,0.94141 -1.61719,1.33594 -0.58594,0.39062 -1.19922,0.71875 -1.84766,0.98828 -0.64844,0.26953 -1.3164,0.47266 -2.0039,0.60938 -0.69141,0.13671 -1.38672,0.20703 -2.08594,0.20703 h -92.36719 c -0.70312,0 -1.39844,-0.0703 -2.08594,-0.20703 -0.6875,-0.13672 -1.35547,-0.33985 -2.0039,-0.60938 -0.64844,-0.26953 -1.26563,-0.59766 -1.84766,-0.98828 -0.58594,-0.39453 -1.125,-0.83594 -1.62109,-1.33594 -0.4961,-0.49609 -0.9375,-1.03906 -1.32813,-1.625 -0.39062,-0.58203 -0.71875,-1.19922 -0.98828,-1.85156 -0.26953,-0.64844 -0.47266,-1.32031 -0.60937,-2.01172 -0.13672,-0.6875 -0.20313,-1.38672 -0.20313,-2.08984 v -55.06641 c 0,-0.70312 0.0664,-1.39844 0.20313,-2.08984 0.13671,-0.69141 0.33984,-1.35938 0.60937,-2.01172 0.26953,-0.64844 0.59766,-1.26563 0.98828,-1.85156 0.39063,-0.58594 0.83203,-1.125 1.32813,-1.625 0.49609,-0.4961 1.03515,-0.94141 1.62109,-1.33204 0.58203,-0.39062 1.19922,-0.72265 1.84766,-0.99218 0.64843,-0.26953 1.3164,-0.47266 2.0039,-0.60938 0.6875,-0.13672 1.38282,-0.20703 2.08594,-0.20703 h 92.36719 c 0.70312,0 1.39844,0.0703 2.08594,0.20703 0.6875,0.13672 1.35546,0.33985 2.0039,0.60938 0.64844,0.26953 1.26563,0.60156 1.84766,0.99218 0.58203,0.39063 1.125,0.83594 1.62109,1.33204 0.4961,0.5 0.9375,1.03906 1.32813,1.625 0.39062,0.58593 0.71875,1.20312 0.98437,1.85156 0.26953,0.65234 0.47266,1.32031 0.60938,2.01172 0.13672,0.6914 0.20703,1.38672 0.20703,2.08984 z m -112.58203,55.06641 c 0,0.6289 0.0625,1.25 0.18359,1.86328 0.12109,0.61719 0.30469,1.21484 0.54297,1.79297 0.23828,0.57812 0.53125,1.1289 0.87891,1.65234 0.34765,0.51953 0.74218,1.00391 1.18359,1.44531 0.44531,0.44532 0.92578,0.83985 1.44531,1.19141 0.51953,0.34766 1.07031,0.64062 1.64844,0.88281 0.57422,0.23828 1.17187,0.41797 1.78516,0.54297 0.61328,0.12109 1.23437,0.18359 1.85937,0.18359 h 92.36719 c 0.625,0 1.24609,-0.0625 1.85937,-0.18359 0.61328,-0.125 1.21094,-0.30469 1.78907,-0.54297 0.57421,-0.24219 1.125,-0.53515 1.64453,-0.88281 0.51953,-0.35156 1,-0.74609 1.44531,-1.19141 0.44141,-0.4414 0.83594,-0.92578 1.18359,-1.44531 0.34766,-0.52344 0.64063,-1.07422 0.87891,-1.65234 0.24219,-0.57813 0.42187,-1.17578 0.54297,-1.79297 0.12109,-0.61328 0.18359,-1.23438 0.18359,-1.86328 v -55.06641 c 0,-0.625 -0.0625,-1.24609 -0.18359,-1.86328 -0.1211,-0.61328 -0.30078,-1.21094 -0.54297,-1.79297 -0.23828,-0.57812 -0.53125,-1.12891 -0.87891,-1.64844 -0.34765,-0.52343 -0.74218,-1.0039 -1.18359,-1.44922 -0.44531,-0.44531 -0.92578,-0.83984 -1.44531,-1.1875 -0.51953,-0.34765 -1.07032,-0.64453 -1.64453,-0.88281 -0.57813,-0.24219 -1.17579,-0.42187 -1.78907,-0.54297 -0.61328,-0.125 -1.23437,-0.18359 -1.85937,-0.18359 h -92.36719 c -0.625,0 -1.24609,0.0586 -1.85937,0.18359 -0.61329,0.1211 -1.21094,0.30078 -1.78516,0.54297 -0.57813,0.23828 -1.12891,0.53516 -1.64844,0.88281 -0.51953,0.34766 -1,0.74219 -1.44531,1.1875 -0.44141,0.44532 -0.83594,0.92579 -1.18359,1.44922 -0.34766,0.51953 -0.64063,1.07032 -0.87891,1.64844 -0.23828,0.58203 -0.42188,1.17969 -0.54297,1.79297 -0.12109,0.61719 -0.18359,1.23828 -0.18359,1.86328 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4654" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4664"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(611.5815,344.04413)"
+ id="g4662">
+ <g
+ id="g4660">
+ <path
+ d="M 7.4375,-5.125 H 3.5625 V 0 H 1.875 v -15.21875 h 5.5625 c 1.65625,0 2.878906,0.40625 3.671875,1.21875 0.789063,0.804688 1.1875,2.03125 1.1875,3.6875 0,3.460938 -1.621094,5.1875 -4.859375,5.1875 z m -3.875,-1.5 h 3.84375 c 2.101562,0 3.15625,-1.226562 3.15625,-3.6875 0,-1.175781 -0.25,-2.039062 -0.75,-2.59375 -0.5,-0.550781 -1.304688,-0.828125 -2.40625,-0.828125 H 3.5625 Z m 0,0"
+ id="path4658" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4672"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(624.62518,344.04413)"
+ id="g4670">
+ <g
+ id="g4668">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4666" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4680"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(635.24928,344.04413)"
+ id="g4678">
+ <g
+ id="g4676">
+ <path
+ d="m 7.28125,-9.5625 h -3.5 v 5.25 c 0,1.261719 0.085938,2.089844 0.265625,2.484375 0.1875,0.398437 0.628906,0.59375 1.328125,0.59375 l 1.953125,-0.125 L 7.4375,0 c -0.980469,0.15625 -1.730469,0.234375 -2.25,0.234375 -1.148438,0 -1.9375,-0.2734375 -2.375,-0.828125 -0.4375,-0.5625 -0.65625,-1.625 -0.65625,-3.1875 V -9.5625 H 0.59375 V -11 h 1.5625 v -3.359375 h 1.625 V -11 h 3.5 z m 0,0"
+ id="path4674" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4688"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(642.96991,344.04413)"
+ id="g4686">
+ <g
+ id="g4684">
+ <path
+ d="m 3.234375,0 h -1.65625 v -15.796875 h 1.65625 v 5.40625 c 1.175781,-0.550781 2.304687,-0.828125 3.390625,-0.828125 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 H 8.6875 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.929688,-9.460938 7.300781,-9.75 6.34375,-9.75 c -0.929688,0 -1.824219,0.171875 -2.6875,0.515625 L 3.234375,-9.09375 Z m 0,0"
+ id="path4682" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4696"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(654.7818,344.04413)"
+ id="g4694">
+ <g
+ id="g4692">
+ <path
+ d="m 1.09375,-5.515625 c 0,-2.007813 0.359375,-3.460937 1.078125,-4.359375 0.71875,-0.894531 1.929687,-1.34375 3.640625,-1.34375 1.707031,0 2.914062,0.449219 3.625,1.34375 0.71875,0.898438 1.078125,2.351562 1.078125,4.359375 0,2 -0.339844,3.460937 -1.015625,4.375 -0.679688,0.90625 -1.914062,1.359375 -3.703125,1.359375 -1.78125,0 -3.011719,-0.453125 -3.6875,-1.359375 -0.679687,-0.914063 -1.015625,-2.375 -1.015625,-4.375 z m 1.703125,-0.03125 c 0,1.605469 0.191406,2.730469 0.578125,3.375 0.382812,0.648437 1.195312,0.96875 2.4375,0.96875 1.238281,0 2.050781,-0.316406 2.4375,-0.953125 0.382812,-0.644531 0.578125,-1.773438 0.578125,-3.390625 0,-1.613281 -0.214844,-2.722656 -0.640625,-3.328125 -0.429688,-0.613281 -1.21875,-0.921875 -2.375,-0.921875 -1.148438,0 -1.9375,0.308594 -2.375,0.921875 -0.429688,0.605469 -0.640625,1.714844 -0.640625,3.328125 z m 0,0"
+ id="path4690" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4704"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(666.39573,344.04413)"
+ id="g4702">
+ <g
+ id="g4700">
+ <path
+ d="M 3.234375,0 H 1.578125 V -11 H 3.21875 v 0.765625 c 1.1875,-0.65625 2.320312,-0.984375 3.40625,-0.984375 1.46875,0 2.453125,0.398438 2.953125,1.1875 0.507813,0.792969 0.765625,2.199219 0.765625,4.21875 V 0 h -1.625 v -5.765625 c 0,-1.519531 -0.152344,-2.5625 -0.453125,-3.125 C 7.960938,-9.460938 7.320312,-9.75 6.34375,-9.75 c -0.480469,0 -0.980469,0.074219 -1.5,0.21875 -0.523438,0.136719 -0.917969,0.273438 -1.1875,0.40625 l -0.421875,0.1875 z m 0,0"
+ id="path4698" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4712"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(622.45064,374.79413)"
+ id="g4710">
+ <g
+ id="g4708">
+ <path
+ d="m 0.28125,-13.703125 v -1.515625 h 11 v 1.515625 H 6.640625 V 0 H 4.96875 v -13.703125 z m 0,0"
+ id="path4706" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4720"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(634.02058,374.79413)"
+ id="g4718">
+ <g
+ id="g4716">
+ <path
+ d="m 0.546875,-11 h 1.65625 l 2.75,9.5625 h 0.71875 L 8.453125,-11 H 10.09375 L 5.515625,4.890625 H 3.875 L 5.296875,0 h -1.625 z m 0,0"
+ id="path4714" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4728"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(644.64468,374.79413)"
+ id="g4726">
+ <g
+ id="g4724">
+ <path
+ d="M 1.578125,4.890625 V -11 H 3.21875 v 0.796875 c 1.113281,-0.675781 2.210938,-1.015625 3.296875,-1.015625 1.394531,0 2.40625,0.445312 3.03125,1.328125 C 10.179688,-9.003906 10.5,-7.539062 10.5,-5.5 c 0,2.042969 -0.375,3.507812 -1.125,4.390625 -0.742188,0.886719 -1.964844,1.328125 -3.671875,1.328125 -0.898437,0 -1.71875,-0.078125 -2.46875,-0.234375 v 4.90625 z M 6.265625,-9.75 c -0.4375,0 -0.914063,0.074219 -1.421875,0.21875 -0.5,0.148438 -0.898438,0.292969 -1.1875,0.4375 l -0.421875,0.234375 v 7.40625 c 1.039063,0.167969 1.832031,0.25 2.375,0.25 1.1875,0 2.019531,-0.335937 2.5,-1.015625 0.476563,-0.675781 0.71875,-1.773438 0.71875,-3.296875 0,-1.53125 -0.21875,-2.617187 -0.65625,-3.265625 C 7.742188,-9.425781 7.109375,-9.75 6.265625,-9.75 Z m 0,0"
+ id="path4722" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4736"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(656.23661,374.79413)"
+ id="g4734">
+ <g
+ id="g4732">
+ <path
+ d="M 9.0625,-1.359375 9.703125,-1.4375 9.75,-0.125 C 8.070312,0.101562 6.640625,0.21875 5.453125,0.21875 c -1.585937,0 -2.710937,-0.457031 -3.375,-1.375 C 1.421875,-2.070312 1.09375,-3.5 1.09375,-5.4375 c 0,-3.851562 1.535156,-5.78125 4.609375,-5.78125 1.476563,0 2.582031,0.417969 3.3125,1.25 0.738281,0.824219 1.109375,2.121094 1.109375,3.890625 L 10.03125,-4.8125 H 2.765625 c 0,1.21875 0.21875,2.121094 0.65625,2.703125 0.445313,0.585937 1.21875,0.875 2.3125,0.875 1.09375,0 2.203125,-0.039063 3.328125,-0.125 z m -0.59375,-4.78125 c 0,-1.34375 -0.21875,-2.289063 -0.65625,-2.84375 -0.429688,-0.5625 -1.132812,-0.84375 -2.109375,-0.84375 -0.96875,0 -1.703125,0.292969 -2.203125,0.875 -0.492188,0.585937 -0.742188,1.523437 -0.75,2.8125 z m 0,0"
+ id="path4730" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#61b05d6a70)"
+ id="g4740"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#848895;fill-opacity:1;stroke:none;stroke-width:0.52087492;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 58.208333,195.13542 v 11.90625 h 48.947917 l 3.96875,-3.96875 V 191.16667 H 62.177083 Z"
- id="path3715-5-6-7-9-8-7-6-56-7"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
+ fill="#306998"
+ d="m 125.32813,478.72266 v -43.44532 c 0,-0.52734 0.0508,-1.04687 0.15625,-1.5625 0.10156,-0.51172 0.25,-1.01172 0.45312,-1.49609 0.19922,-0.48828 0.44531,-0.94922 0.73438,-1.38281 0.29296,-0.4375 0.62109,-0.83985 0.99218,-1.21094 0.3711,-0.375 0.77344,-0.70313 1.20703,-0.99609 0.4375,-0.29297 0.89453,-0.53907 1.37891,-0.73829 0.48437,-0.20312 0.98437,-0.35156 1.49609,-0.45703 0.51172,-0.10156 1.03125,-0.15234 1.55469,-0.15234 h 72.875 c 0.52344,0 1.04297,0.0508 1.55859,0.15234 0.51172,0.10547 1.01172,0.25391 1.49219,0.45703 0.48438,0.19922 0.94531,0.44532 1.37891,0.73829 0.4375,0.29296 0.83984,0.62109 1.20703,0.99609 0.37109,0.37109 0.70312,0.77344 0.99219,1.21094 0.29297,0.43359 0.53906,0.89453 0.73828,1.38281 0.19922,0.48437 0.35156,0.98437 0.45312,1.49609 0.10157,0.51563 0.15235,1.03516 0.15235,1.5625 v 43.44532 c 0,0.52343 -0.0508,1.04296 -0.15235,1.55859 -0.10156,0.51562 -0.2539,1.01562 -0.45312,1.5 -0.19922,0.48437 -0.44531,0.94531 -0.73828,1.38281 -0.28907,0.4375 -0.6211,0.83985 -0.99219,1.21094 -0.36719,0.37109 -0.76953,0.70312 -1.20703,0.99219 -0.4336,0.29297 -0.89453,0.53906 -1.37891,0.74218 -0.48047,0.19922 -0.98047,0.35157 -1.49219,0.45313 -0.51562,0.10156 -1.03515,0.15234 -1.55859,0.15234 h -72.875 c -0.52344,0 -1.04297,-0.0508 -1.55469,-0.15234 -0.51172,-0.10156 -1.01172,-0.25391 -1.49609,-0.45313 -0.48438,-0.20312 -0.94141,-0.44921 -1.37891,-0.74218 -0.43359,-0.28907 -0.83593,-0.6211 -1.20703,-0.99219 -0.37109,-0.37109 -0.69922,-0.77344 -0.99218,-1.21094 -0.28907,-0.4375 -0.53516,-0.89844 -0.73438,-1.38281 -0.20312,-0.48438 -0.35156,-0.98438 -0.45312,-1.5 -0.10547,-0.51563 -0.15625,-1.03516 -0.15625,-1.55859 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4738" />
+ </g>
+ <g
+ clip-path="url(#ea42d02648)"
+ id="g4744"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#848895;fill-opacity:1;stroke:none;stroke-width:0.52087492;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 58.208343,216.30209 v 11.90625 h 48.947907 l 3.96875,-3.96875 V 212.33334 H 62.177093 Z"
- id="path3715-5-6-7-9-8-7-6-56-0"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="65.68634"
- y="179.68727"
- id="text1032"><tspan
- sodipodi:role="line"
- id="tspan1030"
- x="65.68634"
- y="179.68727"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">PythonType1</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="65.326508"
- y="200.85394"
- id="text1032-1"><tspan
- sodipodi:role="line"
- id="tspan1030-1"
- x="65.326508"
- y="200.85394"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">PythonType2</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="65.319458"
- y="222.02061"
- id="text1032-4"><tspan
- sodipodi:role="line"
- id="tspan1030-6"
- x="65.319458"
- y="222.02061"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">PythonType3</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="90.120621"
- y="139.29776"
- id="text1062"><tspan
- sodipodi:role="line"
- id="tspan1060"
- x="90.120621"
- y="139.29776"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">C++</tspan><tspan
- sodipodi:role="line"
- x="90.120621"
- y="152.52693"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
- id="tspan1064">Type</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="135.41069"
- y="138.95909"
- id="text1068"><tspan
- sodipodi:role="line"
- id="tspan1066"
- x="135.41069"
- y="138.95909"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46666622px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">Converter</tspan><tspan
- sodipodi:role="line"
- x="135.41069"
- y="152.18826"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46666622px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
- id="tspan1070">C++ -&gt; Python</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="135.41072"
- y="181.29242"
- id="text1068-9"><tspan
- sodipodi:role="line"
- id="tspan1066-7"
- x="135.41072"
- y="181.29242"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46666622px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">Converter</tspan><tspan
- sodipodi:role="line"
- x="135.41072"
- y="194.52159"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46666622px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
- id="tspan1070-5">Python -&gt; C++</tspan></text>
+ fill="#306998"
+ d="m 214.60547,435.27734 v 43.44141 c 0,0.55469 -0.0508,1.10547 -0.16016,1.65234 -0.10937,0.54297 -0.26953,1.07032 -0.48047,1.58594 -0.21093,0.51172 -0.47265,1 -0.77734,1.46094 -0.30859,0.46094 -0.66016,0.88672 -1.05078,1.28125 -0.39063,0.39453 -0.81641,0.74219 -1.27735,1.05078 -0.46093,0.30859 -0.94531,0.57031 -1.45703,0.78125 -0.51172,0.21484 -1.03906,0.375 -1.58203,0.48047 -0.54297,0.10937 -1.08984,0.16406 -1.64453,0.16406 h -72.87109 c -0.55469,0 -1.10547,-0.0547 -1.64844,-0.16406 -0.54297,-0.10547 -1.07031,-0.26563 -1.57813,-0.48047 -0.51171,-0.21094 -1,-0.47266 -1.46093,-0.78125 -0.46094,-0.30859 -0.88672,-0.65625 -1.27735,-1.05078 -0.39062,-0.39453 -0.73828,-0.82031 -1.04687,-1.28125 -0.30859,-0.46094 -0.56641,-0.94922 -0.78125,-1.46094 -0.21094,-0.51562 -0.37109,-1.04297 -0.47656,-1.58594 -0.10938,-0.54687 -0.16407,-1.09765 -0.16407,-1.65234 v -43.44141 c 0,-0.55468 0.0547,-1.10547 0.16407,-1.65234 0.10547,-0.54297 0.26562,-1.07031 0.47656,-1.58594 0.21484,-0.51172 0.47266,-1 0.78125,-1.46094 0.30859,-0.46093 0.65625,-0.88671 1.04687,-1.28125 0.39063,-0.39453 0.81641,-0.74218 1.27735,-1.05078 0.46093,-0.30859 0.94922,-0.57031 1.46093,-0.78125 0.50782,-0.21484 1.03516,-0.375 1.57813,-0.48047 0.54297,-0.10937 1.09375,-0.16406 1.64844,-0.16406 h 72.87109 c 0.55469,0 1.10156,0.0547 1.64453,0.16406 0.54297,0.10547 1.07031,0.26563 1.58203,0.48047 0.51172,0.21094 1,0.47266 1.45703,0.78125 0.46094,0.3086 0.88672,0.66016 1.27735,1.05078 0.39453,0.39454 0.74219,0.82032 1.05078,1.28125 0.30469,0.46094 0.56641,0.94922 0.77734,1.46094 0.21094,0.51563 0.3711,1.04297 0.48047,1.58985 0.10938,0.54296 0.16016,1.09375 0.16016,1.64843 z m -88.81641,43.44141 c 0,0.49609 0.0469,0.98437 0.14453,1.47266 0.0937,0.48437 0.23829,0.95703 0.42579,1.41406 0.1875,0.45703 0.42187,0.89062 0.69531,1.30078 0.27344,0.41406 0.58594,0.79297 0.93359,1.14453 0.34766,0.34766 0.73047,0.66016 1.14063,0.9375 0.41015,0.27344 0.84375,0.50391 1.29687,0.69531 0.45703,0.1875 0.92578,0.33203 1.41016,0.42969 0.48437,0.0937 0.97265,0.14453 1.46875,0.14453 h 72.87109 c 0.49609,0 0.98438,-0.0508 1.46875,-0.14453 0.48438,-0.0977 0.95313,-0.24219 1.41016,-0.42969 0.45312,-0.1914 0.88672,-0.42187 1.29687,-0.69531 0.41016,-0.27734 0.78906,-0.58984 1.14063,-0.9375 0.34765,-0.35156 0.66015,-0.73047 0.93359,-1.14453 0.27344,-0.41016 0.50781,-0.84375 0.69531,-1.30078 0.1875,-0.45703 0.33203,-0.92969 0.42578,-1.41406 0.0977,-0.48829 0.14454,-0.97657 0.14454,-1.47266 v -43.44141 c 0,-0.49609 -0.0469,-0.98437 -0.14454,-1.47265 -0.0937,-0.48438 -0.23828,-0.95703 -0.42578,-1.41407 -0.1875,-0.45703 -0.42187,-0.89062 -0.69531,-1.30078 -0.27344,-0.41406 -0.58594,-0.79297 -0.93359,-1.14453 -0.35157,-0.34765 -0.73047,-0.66015 -1.14063,-0.9375 -0.41015,-0.27344 -0.84375,-0.5039 -1.29687,-0.69531 -0.45703,-0.1875 -0.92578,-0.33203 -1.41016,-0.42969 -0.48437,-0.0937 -0.97266,-0.14453 -1.46875,-0.14453 h -72.87109 c -0.4961,0 -0.98438,0.0508 -1.46875,0.14453 -0.48438,0.0977 -0.95313,0.24219 -1.41016,0.42969 -0.45312,0.19141 -0.88672,0.42187 -1.29687,0.69531 -0.41016,0.27735 -0.79297,0.58985 -1.14063,0.9375 -0.34765,0.35156 -0.66015,0.73047 -0.93359,1.14453 -0.27344,0.41016 -0.50781,0.84375 -0.69531,1.30078 -0.1875,0.45704 -0.33204,0.92969 -0.42579,1.41407 -0.0977,0.48828 -0.14453,0.97656 -0.14453,1.47265 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4742" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4752"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(143.38693,451.22147)"
+ id="g4750">
+ <g
+ id="g4748">
+ <path
+ d="M 5.875,-4.046875 H 2.8125 V 0 H 1.46875 V -12.015625 H 5.875 c 1.300781,0 2.265625,0.320313 2.890625,0.953125 0.625,0.636719 0.9375,1.609375 0.9375,2.921875 0,2.730469 -1.277344,4.09375 -3.828125,4.09375 z M 2.8125,-5.21875 h 3.03125 c 1.65625,0 2.484375,-0.972656 2.484375,-2.921875 0,-0.925781 -0.199219,-1.601563 -0.59375,-2.03125 -0.386719,-0.4375 -1.015625,-0.65625 -1.890625,-0.65625 H 2.8125 Z m 0,0"
+ id="path4746" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4760"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(153.67768,451.22147)"
+ id="g4758">
+ <g
+ id="g4756">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path4754" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4768"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.05952,451.22147)"
+ id="g4766">
+ <g
+ id="g4764">
+ <path
+ d="M 5.75,-7.546875 H 2.984375 v 4.140625 c 0,1 0.070313,1.65625 0.21875,1.96875 0.144531,0.3125 0.488281,0.46875 1.03125,0.46875 L 5.78125,-1.078125 5.875,0 C 5.09375,0.125 4.5,0.1875 4.09375,0.1875 3.195312,0.1875 2.570312,-0.03125 2.21875,-0.46875 1.875,-0.90625 1.703125,-1.742188 1.703125,-2.984375 v -4.5625 H 0.46875 v -1.125 h 1.234375 v -2.65625 h 1.28125 v 2.65625 H 5.75 Z m 0,0"
+ id="path4762" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4776"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(168.15067,451.22147)"
+ id="g4774">
+ <g
+ id="g4772">
+ <path
+ d="M 2.546875,0 H 1.25 v -12.46875 h 1.296875 v 4.28125 c 0.925781,-0.445312 1.816406,-0.671875 2.671875,-0.671875 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.859375 V -4.546875 C 6.859375,-5.753906 6.738281,-6.578125 6.5,-7.015625 6.257812,-7.460938 5.757812,-7.6875 5,-7.6875 c -0.730469,0 -1.4375,0.132812 -2.125,0.390625 l -0.328125,0.125 z m 0,0"
+ id="path4770" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4784"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(177.4696,451.22147)"
+ id="g4782">
+ <g
+ id="g4780">
+ <path
+ d="m 0.875,-4.359375 c 0,-1.582031 0.28125,-2.726563 0.84375,-3.4375 0.5625,-0.707031 1.515625,-1.0625 2.859375,-1.0625 1.351563,0 2.3125,0.355469 2.875,1.0625 0.5625,0.710937 0.84375,1.855469 0.84375,3.4375 C 8.296875,-2.773438 8.03125,-1.625 7.5,-0.90625 6.96875,-0.1875 5.992188,0.171875 4.578125,0.171875 c -1.40625,0 -2.375,-0.359375 -2.90625,-1.078125 C 1.140625,-1.625 0.875,-2.773438 0.875,-4.359375 Z M 2.203125,-4.375 c 0,1.261719 0.148437,2.148438 0.453125,2.65625 0.3125,0.511719 0.957031,0.765625 1.9375,0.765625 0.976562,0 1.617188,-0.25 1.921875,-0.75 C 6.816406,-2.210938 6.96875,-3.101562 6.96875,-4.375 6.96875,-5.644531 6.796875,-6.519531 6.453125,-7 6.117188,-7.476562 5.5,-7.71875 4.59375,-7.71875 3.6875,-7.71875 3.0625,-7.476562 2.71875,-7 2.375,-6.519531 2.203125,-5.644531 2.203125,-4.375 Z m 0,0"
+ id="path4778" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4792"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(186.63236,451.22147)"
+ id="g4790">
+ <g
+ id="g4788">
+ <path
+ d="M 2.546875,0 H 1.25 v -8.671875 h 1.28125 v 0.59375 c 0.9375,-0.519531 1.832031,-0.78125 2.6875,-0.78125 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.875 v -4.546875 c 0,-1.207031 -0.121094,-2.03125 -0.359375,-2.46875 C 6.273438,-7.460938 5.769531,-7.6875 5,-7.6875 c -0.375,0 -0.765625,0.058594 -1.171875,0.171875 -0.40625,0.105469 -0.726563,0.210937 -0.953125,0.3125 l -0.328125,0.15625 z m 0,0"
+ id="path4786" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4800"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(145.18979,475.48154)"
+ id="g4798">
+ <g
+ id="g4796">
+ <path
+ d="m 0.21875,-10.8125 v -1.203125 h 8.6875 V -10.8125 H 5.25 V 0 H 3.921875 v -10.8125 z m 0,0"
+ id="path4794" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4808"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(154.31784,475.48154)"
+ id="g4806">
+ <g
+ id="g4804">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path4802" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4816"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.69968,475.48154)"
+ id="g4814">
+ <g
+ id="g4812">
+ <path
+ d="M 1.25,3.859375 V -8.671875 H 2.53125 V -8.0625 c 0.882812,-0.53125 1.753906,-0.796875 2.609375,-0.796875 1.09375,0 1.890625,0.355469 2.390625,1.0625 0.5,0.699219 0.75,1.855469 0.75,3.46875 0,1.605469 -0.292969,2.757813 -0.875,3.453125 C 6.820312,-0.175781 5.851562,0.171875 4.5,0.171875 c -0.710938,0 -1.359375,-0.0625 -1.953125,-0.1875 v 3.875 z M 4.953125,-7.6875 c -0.355469,0 -0.730469,0.058594 -1.125,0.171875 C 3.429688,-7.398438 3.113281,-7.285156 2.875,-7.171875 L 2.546875,-7 v 5.859375 c 0.820313,0.125 1.445313,0.1875 1.875,0.1875 0.9375,0 1.59375,-0.265625 1.96875,-0.796875 0.382813,-0.53125 0.578125,-1.394531 0.578125,-2.59375 0,-1.207031 -0.171875,-2.066406 -0.515625,-2.578125 -0.34375,-0.507813 -0.84375,-0.765625 -1.5,-0.765625 z m 0,0"
+ id="path4810" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4824"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(171.84508,475.48154)"
+ id="g4822">
+ <g
+ id="g4820">
+ <path
+ d="m 7.15625,-1.078125 0.5,-0.046875 0.03125,1.015625 C 6.375,0.078125 5.25,0.171875 4.3125,0.171875 3.0625,0.171875 2.175781,-0.1875 1.65625,-0.90625 1.132812,-1.632812 0.875,-2.757812 0.875,-4.28125 c 0,-3.050781 1.207031,-4.578125 3.625,-4.578125 1.164062,0 2.035156,0.328125 2.609375,0.984375 0.582031,0.65625 0.875,1.683594 0.875,3.078125 l -0.0625,1 H 2.1875 c 0,0.960937 0.171875,1.671875 0.515625,2.140625 0.351563,0.460938 0.957031,0.6875 1.8125,0.6875 0.863281,0 1.742187,-0.035156 2.640625,-0.109375 z M 6.6875,-4.84375 c 0,-1.0625 -0.171875,-1.8125 -0.515625,-2.25 C 5.828125,-7.539062 5.269531,-7.765625 4.5,-7.765625 c -0.773438,0 -1.351562,0.234375 -1.734375,0.703125 -0.386719,0.460938 -0.585937,1.199219 -0.59375,2.21875 z m 0,0"
+ id="path4818" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4830"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(180.6087,475.48154)"
+ id="g4828">
+ <g
+ id="g4826" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4838"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(184.42651,475.48154)"
+ id="g4836">
+ <g
+ id="g4834">
+ <path
+ d="M 6.75,-11.453125 V 0 H 5.421875 V -9.96875 L 2.46875,-8.015625 1.859375,-9.03125 5.5,-11.453125 Z m 0,0"
+ id="path4832" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#84bd6662f0)"
+ id="g4842"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#3a4055;fill-opacity:1;stroke:none;stroke-width:0.67261654;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 211.66667,175.29167 V 201.75 h 37.04166 L 254,196.45833 V 170 h -37.04167 z"
- id="path3715-5-6-7-9-8-7-6-3-9"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="232.99562"
- y="181.63109"
- id="text1062-7"><tspan
- sodipodi:role="line"
- id="tspan1060-4"
- x="232.99562"
- y="181.63109"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">C++</tspan><tspan
- sodipodi:role="line"
- x="232.99562"
- y="194.86026"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
- id="tspan1064-9">Type</tspan></text>
+ fill="#306998"
+ d="m 125.32813,548.84766 v -43.44532 c 0,-0.52343 0.0508,-1.04297 0.15625,-1.55859 0.10156,-0.51563 0.25,-1.01563 0.45312,-1.5 0.19922,-0.48438 0.44531,-0.94531 0.73438,-1.38281 0.29296,-0.4336 0.62109,-0.83985 0.99218,-1.21094 0.3711,-0.37109 0.77344,-0.70313 1.20703,-0.99219 0.4375,-0.29297 0.89453,-0.53906 1.37891,-0.73828 0.48437,-0.20312 0.98437,-0.35547 1.49609,-0.45703 0.51172,-0.10156 1.03125,-0.15234 1.55469,-0.15234 h 72.875 c 0.52344,0 1.04297,0.0508 1.55859,0.15234 0.51172,0.10156 1.01172,0.25391 1.49219,0.45703 0.48438,0.19922 0.94531,0.44531 1.37891,0.73828 0.4375,0.28906 0.83984,0.6211 1.20703,0.99219 0.37109,0.37109 0.70312,0.77734 0.99219,1.21094 0.29297,0.4375 0.53906,0.89843 0.73828,1.38281 0.19922,0.48437 0.35156,0.98437 0.45312,1.5 0.10157,0.51562 0.15235,1.03516 0.15235,1.55859 v 43.44532 c 0,0.52734 -0.0508,1.04687 -0.15235,1.5625 -0.10156,0.51171 -0.2539,1.01171 -0.45312,1.5 -0.19922,0.48437 -0.44531,0.94531 -0.73828,1.3789 -0.28907,0.4375 -0.6211,0.84375 -0.99219,1.21485 -0.36719,0.37109 -0.76953,0.69921 -1.20703,0.99218 -0.4336,0.29297 -0.89453,0.53907 -1.37891,0.73828 -0.48047,0.20313 -0.98047,0.35547 -1.49219,0.45704 -0.51562,0.10156 -1.03515,0.15234 -1.55859,0.15234 h -72.875 c -0.52344,0 -1.04297,-0.0508 -1.55469,-0.15234 -0.51172,-0.10157 -1.01172,-0.25391 -1.49609,-0.45704 -0.48438,-0.19921 -0.94141,-0.44531 -1.37891,-0.73828 -0.43359,-0.29297 -0.83593,-0.62109 -1.20703,-0.99218 -0.37109,-0.3711 -0.69922,-0.77735 -0.99218,-1.21485 -0.28907,-0.43359 -0.53516,-0.89453 -0.73438,-1.3789 -0.20312,-0.48829 -0.35156,-0.98829 -0.45312,-1.5 -0.10547,-0.51563 -0.15625,-1.03516 -0.15625,-1.5625 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4840" />
+ </g>
+ <g
+ clip-path="url(#728d290ff8)"
+ id="g4846"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:#848895;fill-opacity:1;stroke:none;stroke-width:0.52087492;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 211.66667,131.63542 v 11.90625 h 48.94791 l 3.96875,-3.96875 v -11.90625 h -48.94791 z"
- id="path3715-5-6-7-9-8-7-6-56-0-1"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
- x="220.67876"
- y="137.35394"
- id="text1032-4-7"><tspan
- sodipodi:role="line"
- id="tspan1030-6-0"
- x="220.67876"
- y="137.35394"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05555534px;font-family:Titillium;-inkscape-font-specification:'Titillium, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332">PythonType</tspan></text>
+ fill="#306998"
+ d="m 214.60547,505.40234 v 43.44532 c 0,0.55468 -0.0508,1.10546 -0.16016,1.64843 -0.10937,0.54688 -0.26953,1.07422 -0.48047,1.58594 -0.21093,0.51563 -0.47265,1 -0.77734,1.46484 -0.30859,0.46094 -0.66016,0.88672 -1.05078,1.28125 -0.39063,0.39063 -0.81641,0.74219 -1.27735,1.05079 -0.46093,0.30859 -0.94531,0.57031 -1.45703,0.78125 -0.51172,0.21093 -1.03906,0.37109 -1.58203,0.48046 -0.54297,0.10938 -1.08984,0.16407 -1.64453,0.16407 h -72.87109 c -0.55469,0 -1.10547,-0.0547 -1.64844,-0.16407 -0.54297,-0.10937 -1.07031,-0.26953 -1.57813,-0.48046 -0.51171,-0.21094 -1,-0.47266 -1.46093,-0.78125 -0.46094,-0.3086 -0.88672,-0.66016 -1.27735,-1.05079 -0.39062,-0.39453 -0.73828,-0.82031 -1.04687,-1.28125 -0.30859,-0.46484 -0.56641,-0.94921 -0.78125,-1.46484 -0.21094,-0.51172 -0.37109,-1.03906 -0.47656,-1.58594 -0.10938,-0.54297 -0.16407,-1.09375 -0.16407,-1.64843 v -43.44532 c 0,-0.55468 0.0547,-1.10156 0.16407,-1.64843 0.10547,-0.54297 0.26562,-1.07422 0.47656,-1.58594 0.21484,-0.51172 0.47266,-1 0.78125,-1.46094 0.30859,-0.46094 0.65625,-0.89062 1.04687,-1.28125 0.39063,-0.39453 0.81641,-0.74609 1.27735,-1.05469 0.46093,-0.30859 0.94922,-0.5664 1.46093,-0.78125 0.50782,-0.21093 1.03516,-0.37109 1.57813,-0.48047 0.54297,-0.10937 1.09375,-0.16015 1.64844,-0.16015 h 72.87109 c 0.55469,0 1.10156,0.0547 1.64453,0.16015 0.54297,0.10938 1.07031,0.26954 1.58203,0.48438 0.51172,0.21094 1,0.47266 1.45703,0.78125 0.46094,0.30859 0.88672,0.65625 1.27735,1.05078 0.39453,0.39063 0.74219,0.82031 1.05078,1.28125 0.30469,0.46094 0.56641,0.94922 0.77734,1.46094 0.21094,0.51172 0.3711,1.04297 0.48047,1.58594 0.10938,0.54687 0.16016,1.09375 0.16016,1.64843 z m -88.81641,43.44532 c 0,0.49609 0.0469,0.98437 0.14453,1.46875 0.0937,0.48828 0.23829,0.95703 0.42579,1.41406 0.1875,0.45703 0.42187,0.89453 0.69531,1.30469 0.27344,0.41015 0.58594,0.79296 0.93359,1.14062 0.34766,0.35156 0.73047,0.66406 1.14063,0.9375 0.41015,0.27734 0.84375,0.50781 1.29687,0.69922 0.45703,0.1875 0.92578,0.33203 1.41016,0.42578 0.48437,0.0977 0.97265,0.14453 1.46875,0.14453 h 72.87109 c 0.49609,0 0.98438,-0.0469 1.46875,-0.14453 0.48438,-0.0937 0.95313,-0.23828 1.41016,-0.42578 0.45312,-0.19141 0.88672,-0.42188 1.29687,-0.69922 0.41016,-0.27344 0.78906,-0.58594 1.14063,-0.9375 0.34765,-0.34766 0.66015,-0.73047 0.93359,-1.14062 0.27344,-0.41016 0.50781,-0.84766 0.69531,-1.30469 0.1875,-0.45703 0.33203,-0.92578 0.42578,-1.41406 0.0977,-0.48438 0.14454,-0.97266 0.14454,-1.46875 v -43.44532 c 0,-0.49218 -0.0469,-0.98437 -0.14454,-1.46875 -0.0937,-0.48437 -0.23828,-0.95703 -0.42578,-1.41406 -0.1875,-0.45703 -0.42187,-0.89062 -0.69531,-1.30469 -0.27344,-0.41015 -0.58594,-0.78906 -0.93359,-1.14062 -0.35157,-0.35156 -0.73047,-0.66406 -1.14063,-0.9375 -0.41015,-0.27344 -0.84375,-0.50781 -1.29687,-0.69531 -0.45703,-0.19141 -0.92578,-0.33204 -1.41016,-0.42969 -0.48437,-0.0977 -0.97266,-0.14453 -1.46875,-0.14453 h -72.87109 c -0.4961,0 -0.98438,0.0469 -1.46875,0.14453 -0.48438,0.0976 -0.95313,0.23828 -1.41016,0.42969 -0.45312,0.1875 -0.88672,0.42187 -1.29687,0.69531 -0.41016,0.27344 -0.79297,0.58594 -1.14063,0.9375 -0.34765,0.35156 -0.66015,0.73047 -0.93359,1.14062 -0.27344,0.41407 -0.50781,0.84766 -0.69531,1.30469 -0.1875,0.45703 -0.33204,0.92969 -0.42579,1.41406 -0.0977,0.48438 -0.14453,0.97657 -0.14453,1.46875 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4844" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4854"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(143.38693,521.34911)"
+ id="g4852">
+ <g
+ id="g4850">
+ <path
+ d="M 5.875,-4.046875 H 2.8125 V 0 H 1.46875 V -12.015625 H 5.875 c 1.300781,0 2.265625,0.320313 2.890625,0.953125 0.625,0.636719 0.9375,1.609375 0.9375,2.921875 0,2.730469 -1.277344,4.09375 -3.828125,4.09375 z M 2.8125,-5.21875 h 3.03125 c 1.65625,0 2.484375,-0.972656 2.484375,-2.921875 0,-0.925781 -0.199219,-1.601563 -0.59375,-2.03125 -0.386719,-0.4375 -1.015625,-0.65625 -1.890625,-0.65625 H 2.8125 Z m 0,0"
+ id="path4848" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4862"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(153.67768,521.34911)"
+ id="g4860">
+ <g
+ id="g4858">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path4856" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4870"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.05952,521.34911)"
+ id="g4868">
+ <g
+ id="g4866">
+ <path
+ d="M 5.75,-7.546875 H 2.984375 v 4.140625 c 0,1 0.070313,1.65625 0.21875,1.96875 0.144531,0.3125 0.488281,0.46875 1.03125,0.46875 L 5.78125,-1.078125 5.875,0 C 5.09375,0.125 4.5,0.1875 4.09375,0.1875 3.195312,0.1875 2.570312,-0.03125 2.21875,-0.46875 1.875,-0.90625 1.703125,-1.742188 1.703125,-2.984375 v -4.5625 H 0.46875 v -1.125 h 1.234375 v -2.65625 h 1.28125 v 2.65625 H 5.75 Z m 0,0"
+ id="path4864" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4878"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(168.15067,521.34911)"
+ id="g4876">
+ <g
+ id="g4874">
+ <path
+ d="M 2.546875,0 H 1.25 v -12.46875 h 1.296875 v 4.28125 c 0.925781,-0.445312 1.816406,-0.671875 2.671875,-0.671875 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.859375 V -4.546875 C 6.859375,-5.753906 6.738281,-6.578125 6.5,-7.015625 6.257812,-7.460938 5.757812,-7.6875 5,-7.6875 c -0.730469,0 -1.4375,0.132812 -2.125,0.390625 l -0.328125,0.125 z m 0,0"
+ id="path4872" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4886"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(177.4696,521.34911)"
+ id="g4884">
+ <g
+ id="g4882">
+ <path
+ d="m 0.875,-4.359375 c 0,-1.582031 0.28125,-2.726563 0.84375,-3.4375 0.5625,-0.707031 1.515625,-1.0625 2.859375,-1.0625 1.351563,0 2.3125,0.355469 2.875,1.0625 0.5625,0.710937 0.84375,1.855469 0.84375,3.4375 C 8.296875,-2.773438 8.03125,-1.625 7.5,-0.90625 6.96875,-0.1875 5.992188,0.171875 4.578125,0.171875 c -1.40625,0 -2.375,-0.359375 -2.90625,-1.078125 C 1.140625,-1.625 0.875,-2.773438 0.875,-4.359375 Z M 2.203125,-4.375 c 0,1.261719 0.148437,2.148438 0.453125,2.65625 0.3125,0.511719 0.957031,0.765625 1.9375,0.765625 0.976562,0 1.617188,-0.25 1.921875,-0.75 C 6.816406,-2.210938 6.96875,-3.101562 6.96875,-4.375 6.96875,-5.644531 6.796875,-6.519531 6.453125,-7 6.117188,-7.476562 5.5,-7.71875 4.59375,-7.71875 3.6875,-7.71875 3.0625,-7.476562 2.71875,-7 2.375,-6.519531 2.203125,-5.644531 2.203125,-4.375 Z m 0,0"
+ id="path4880" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4894"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(186.63236,521.34911)"
+ id="g4892">
+ <g
+ id="g4890">
+ <path
+ d="M 2.546875,0 H 1.25 v -8.671875 h 1.28125 v 0.59375 c 0.9375,-0.519531 1.832031,-0.78125 2.6875,-0.78125 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.875 v -4.546875 c 0,-1.207031 -0.121094,-2.03125 -0.359375,-2.46875 C 6.273438,-7.460938 5.769531,-7.6875 5,-7.6875 c -0.375,0 -0.765625,0.058594 -1.171875,0.171875 -0.40625,0.105469 -0.726563,0.210937 -0.953125,0.3125 l -0.328125,0.15625 z m 0,0"
+ id="path4888" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4902"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(145.18979,545.60918)"
+ id="g4900">
+ <g
+ id="g4898">
+ <path
+ d="m 0.21875,-10.8125 v -1.203125 h 8.6875 V -10.8125 H 5.25 V 0 H 3.921875 v -10.8125 z m 0,0"
+ id="path4896" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4910"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(154.31784,545.60918)"
+ id="g4908">
+ <g
+ id="g4906">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path4904" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4918"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.69968,545.60918)"
+ id="g4916">
+ <g
+ id="g4914">
+ <path
+ d="M 1.25,3.859375 V -8.671875 H 2.53125 V -8.0625 c 0.882812,-0.53125 1.753906,-0.796875 2.609375,-0.796875 1.09375,0 1.890625,0.355469 2.390625,1.0625 0.5,0.699219 0.75,1.855469 0.75,3.46875 0,1.605469 -0.292969,2.757813 -0.875,3.453125 C 6.820312,-0.175781 5.851562,0.171875 4.5,0.171875 c -0.710938,0 -1.359375,-0.0625 -1.953125,-0.1875 v 3.875 z M 4.953125,-7.6875 c -0.355469,0 -0.730469,0.058594 -1.125,0.171875 C 3.429688,-7.398438 3.113281,-7.285156 2.875,-7.171875 L 2.546875,-7 v 5.859375 c 0.820313,0.125 1.445313,0.1875 1.875,0.1875 0.9375,0 1.59375,-0.265625 1.96875,-0.796875 0.382813,-0.53125 0.578125,-1.394531 0.578125,-2.59375 0,-1.207031 -0.171875,-2.066406 -0.515625,-2.578125 -0.34375,-0.507813 -0.84375,-0.765625 -1.5,-0.765625 z m 0,0"
+ id="path4912" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4926"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(171.84508,545.60918)"
+ id="g4924">
+ <g
+ id="g4922">
+ <path
+ d="m 7.15625,-1.078125 0.5,-0.046875 0.03125,1.015625 C 6.375,0.078125 5.25,0.171875 4.3125,0.171875 3.0625,0.171875 2.175781,-0.1875 1.65625,-0.90625 1.132812,-1.632812 0.875,-2.757812 0.875,-4.28125 c 0,-3.050781 1.207031,-4.578125 3.625,-4.578125 1.164062,0 2.035156,0.328125 2.609375,0.984375 0.582031,0.65625 0.875,1.683594 0.875,3.078125 l -0.0625,1 H 2.1875 c 0,0.960937 0.171875,1.671875 0.515625,2.140625 0.351563,0.460938 0.957031,0.6875 1.8125,0.6875 0.863281,0 1.742187,-0.035156 2.640625,-0.109375 z M 6.6875,-4.84375 c 0,-1.0625 -0.171875,-1.8125 -0.515625,-2.25 C 5.828125,-7.539062 5.269531,-7.765625 4.5,-7.765625 c -0.773438,0 -1.351562,0.234375 -1.734375,0.703125 -0.386719,0.460938 -0.585937,1.199219 -0.59375,2.21875 z m 0,0"
+ id="path4920" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4932"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(180.6087,545.60918)"
+ id="g4930">
+ <g
+ id="g4928" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4940"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(184.42651,545.60918)"
+ id="g4938">
+ <g
+ id="g4936">
+ <path
+ d="m 8.515625,0 h -7.3125 v -1.125 l 3.34375,-3.53125 c 0.582031,-0.601562 1.003906,-1.0625 1.265625,-1.375 0.269531,-0.3125 0.507812,-0.679688 0.71875,-1.109375 0.21875,-0.425781 0.328125,-0.851563 0.328125,-1.28125 0,-0.738281 -0.203125,-1.257813 -0.609375,-1.5625 -0.40625,-0.300781 -1.039062,-0.453125 -1.890625,-0.453125 -0.75,0 -1.589844,0.101562 -2.515625,0.296875 l -0.453125,0.09375 -0.109375,-1.109375 c 1.101562,-0.3125 2.238281,-0.46875 3.40625,-0.46875 1.164062,0 2.046875,0.246094 2.640625,0.734375 0.601563,0.492187 0.90625,1.265625 0.90625,2.328125 0,0.8125 -0.183594,1.523438 -0.546875,2.125 -0.355469,0.605469 -0.976562,1.328125 -1.859375,2.171875 L 2.78125,-1.15625 h 5.734375 z m 0,0"
+ id="path4934" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#00b091b271)"
+ id="g4944"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
- d="M 111.125,143.54167 H 127"
- id="path1149"
- inkscape:connector-curvature="0" />
+ fill="#306998"
+ d="m 125.32813,618.67969 v -43.44532 c 0,-0.52343 0.0508,-1.04687 0.15625,-1.55859 0.10156,-0.51562 0.25,-1.01562 0.45312,-1.5 0.19922,-0.48437 0.44531,-0.94531 0.73438,-1.38281 0.29296,-0.4375 0.62109,-0.83985 0.99218,-1.21094 0.3711,-0.37109 0.77344,-0.70312 1.20703,-0.99609 0.4375,-0.28907 0.89453,-0.53907 1.37891,-0.73828 0.48437,-0.19922 0.98437,-0.35157 1.49609,-0.45313 0.51172,-0.10547 1.03125,-0.15625 1.55469,-0.15625 h 72.875 c 0.52344,0 1.04297,0.0508 1.55859,0.15625 0.51172,0.10156 1.01172,0.25391 1.49219,0.45313 0.48438,0.19921 0.94531,0.44921 1.37891,0.73828 0.4375,0.29297 0.83984,0.625 1.20703,0.99609 0.37109,0.37109 0.70312,0.77344 0.99219,1.21094 0.29297,0.4375 0.53906,0.89844 0.73828,1.38281 0.19922,0.48438 0.35156,0.98438 0.45312,1.5 0.10157,0.51172 0.15235,1.03516 0.15235,1.55859 v 43.44532 c 0,0.52343 -0.0508,1.04297 -0.15235,1.55859 -0.10156,0.51563 -0.2539,1.01563 -0.45312,1.5 -0.19922,0.48438 -0.44531,0.94531 -0.73828,1.38281 -0.28907,0.4375 -0.6211,0.83985 -0.99219,1.21094 -0.36719,0.37109 -0.76953,0.70313 -1.20703,0.99609 -0.4336,0.28907 -0.89453,0.53516 -1.37891,0.73829 -0.48047,0.19921 -0.98047,0.35156 -1.49219,0.45312 -0.51562,0.10547 -1.03515,0.15625 -1.55859,0.15625 h -72.875 c -0.52344,0 -1.04297,-0.0508 -1.55469,-0.15625 -0.51172,-0.10156 -1.01172,-0.25391 -1.49609,-0.45312 -0.48438,-0.20313 -0.94141,-0.44922 -1.37891,-0.73829 -0.43359,-0.29296 -0.83593,-0.625 -1.20703,-0.99609 -0.37109,-0.37109 -0.69922,-0.77344 -0.99218,-1.21094 -0.28907,-0.4375 -0.53516,-0.89843 -0.73438,-1.38281 -0.20312,-0.48437 -0.35156,-0.98437 -0.45312,-1.5 -0.10547,-0.51562 -0.15625,-1.03516 -0.15625,-1.55859 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4942" />
+ </g>
+ <g
+ clip-path="url(#be13ebcaaa)"
+ id="g4948"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1443)"
- d="M 111.125,175.29167 H 127"
- id="path1433"
- inkscape:connector-curvature="0" />
+ fill="#306998"
+ d="m 214.60547,575.23437 v 43.44141 c 0,0.55859 -0.0508,1.10547 -0.16016,1.65234 -0.10937,0.54297 -0.26953,1.07422 -0.48047,1.58594 -0.21093,0.51172 -0.47265,1 -0.77734,1.46094 -0.30859,0.46094 -0.66016,0.89062 -1.05078,1.28125 -0.39063,0.39453 -0.81641,0.74219 -1.27735,1.05078 -0.46093,0.30859 -0.94531,0.57031 -1.45703,0.78125 -0.51172,0.21484 -1.03906,0.375 -1.58203,0.48438 -0.54297,0.10546 -1.08984,0.16015 -1.64453,0.16015 h -72.87109 c -0.55469,0 -1.10547,-0.0547 -1.64844,-0.16015 -0.54297,-0.10938 -1.07031,-0.26954 -1.57813,-0.48438 -0.51171,-0.21094 -1,-0.47266 -1.46093,-0.78125 -0.46094,-0.30859 -0.88672,-0.65625 -1.27735,-1.05078 -0.39062,-0.39063 -0.73828,-0.82031 -1.04687,-1.28125 -0.30859,-0.46094 -0.56641,-0.94922 -0.78125,-1.46094 -0.21094,-0.51172 -0.37109,-1.04297 -0.47656,-1.58594 -0.10938,-0.54687 -0.16407,-1.09375 -0.16407,-1.65234 v -43.44141 c 0,-0.55468 0.0547,-1.10546 0.16407,-1.64843 0.10547,-0.54688 0.26562,-1.07422 0.47656,-1.58594 0.21484,-0.51563 0.47266,-1.00391 0.78125,-1.46484 0.30859,-0.46094 0.65625,-0.88672 1.04687,-1.28125 0.39063,-0.39063 0.81641,-0.74219 1.27735,-1.05079 0.46093,-0.30859 0.94922,-0.57031 1.46093,-0.78125 0.50782,-0.21484 1.03516,-0.375 1.57813,-0.48046 0.54297,-0.10938 1.09375,-0.16407 1.64844,-0.16407 h 72.87109 c 0.55469,0 1.10156,0.0547 1.64453,0.16407 0.54297,0.10937 1.07031,0.26953 1.58203,0.48046 0.51172,0.21094 1,0.47266 1.45703,0.78125 0.46094,0.3086 0.88672,0.66016 1.27735,1.05079 0.39453,0.39453 0.74219,0.82031 1.05078,1.28125 0.30469,0.46484 0.56641,0.94921 0.77734,1.46484 0.21094,0.51172 0.3711,1.03906 0.48047,1.58594 0.10938,0.54297 0.16016,1.09375 0.16016,1.64843 z m -88.81641,43.44141 c 0,0.49609 0.0469,0.98828 0.14453,1.47266 0.0937,0.48437 0.23829,0.95703 0.42579,1.41406 0.1875,0.45703 0.42187,0.89062 0.69531,1.30078 0.27344,0.41406 0.58594,0.79297 0.93359,1.14453 0.34766,0.34766 0.73047,0.66016 1.14063,0.9375 0.41015,0.27344 0.84375,0.50781 1.29687,0.69531 0.45703,0.19141 0.92578,0.33204 1.41016,0.42969 0.48437,0.0977 0.97265,0.14453 1.46875,0.14453 h 72.87109 c 0.49609,0 0.98438,-0.0469 1.46875,-0.14453 0.48438,-0.0976 0.95313,-0.23828 1.41016,-0.42969 0.45312,-0.1875 0.88672,-0.42187 1.29687,-0.69531 0.41016,-0.27734 0.78906,-0.58984 1.14063,-0.9375 0.34765,-0.35156 0.66015,-0.73047 0.93359,-1.14453 0.27344,-0.41016 0.50781,-0.84375 0.69531,-1.30078 0.1875,-0.45703 0.33203,-0.92969 0.42578,-1.41406 0.0977,-0.48438 0.14454,-0.97657 0.14454,-1.47266 v -43.44141 c 0,-0.49609 -0.0469,-0.98437 -0.14454,-1.46875 -0.0937,-0.48828 -0.23828,-0.95703 -0.42578,-1.41406 -0.1875,-0.45703 -0.42187,-0.89453 -0.69531,-1.30469 -0.27344,-0.41015 -0.58594,-0.79296 -0.93359,-1.14062 -0.35157,-0.35156 -0.73047,-0.66406 -1.14063,-0.9375 -0.41015,-0.27734 -0.84375,-0.50781 -1.29687,-0.69922 -0.45703,-0.1875 -0.92578,-0.33203 -1.41016,-0.42969 -0.48437,-0.0937 -0.97266,-0.14453 -1.46875,-0.14453 h -72.87109 c -0.4961,0 -0.98438,0.0508 -1.46875,0.14453 -0.48438,0.0977 -0.95313,0.24219 -1.41016,0.42969 -0.45312,0.19141 -0.88672,0.42188 -1.29687,0.69922 -0.41016,0.27344 -0.79297,0.58594 -1.14063,0.9375 -0.34765,0.34766 -0.66015,0.73047 -0.93359,1.14062 -0.27344,0.41016 -0.50781,0.84766 -0.69531,1.30469 -0.1875,0.45703 -0.33204,0.92578 -0.42579,1.41406 -0.0977,0.48438 -0.14453,0.97266 -0.14453,1.46875 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path4946" />
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4956"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(143.38693,591.17926)"
+ id="g4954">
+ <g
+ id="g4952">
+ <path
+ d="M 5.875,-4.046875 H 2.8125 V 0 H 1.46875 V -12.015625 H 5.875 c 1.300781,0 2.265625,0.320313 2.890625,0.953125 0.625,0.636719 0.9375,1.609375 0.9375,2.921875 0,2.730469 -1.277344,4.09375 -3.828125,4.09375 z M 2.8125,-5.21875 h 3.03125 c 1.65625,0 2.484375,-0.972656 2.484375,-2.921875 0,-0.925781 -0.199219,-1.601563 -0.59375,-2.03125 -0.386719,-0.4375 -1.015625,-0.65625 -1.890625,-0.65625 H 2.8125 Z m 0,0"
+ id="path4950" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4964"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(153.67768,591.17926)"
+ id="g4962">
+ <g
+ id="g4960">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path4958" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4972"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.05952,591.17926)"
+ id="g4970">
+ <g
+ id="g4968">
+ <path
+ d="M 5.75,-7.546875 H 2.984375 v 4.140625 c 0,1 0.070313,1.65625 0.21875,1.96875 0.144531,0.3125 0.488281,0.46875 1.03125,0.46875 L 5.78125,-1.078125 5.875,0 C 5.09375,0.125 4.5,0.1875 4.09375,0.1875 3.195312,0.1875 2.570312,-0.03125 2.21875,-0.46875 1.875,-0.90625 1.703125,-1.742188 1.703125,-2.984375 v -4.5625 H 0.46875 v -1.125 h 1.234375 v -2.65625 h 1.28125 v 2.65625 H 5.75 Z m 0,0"
+ id="path4966" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4980"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(168.15067,591.17926)"
+ id="g4978">
+ <g
+ id="g4976">
+ <path
+ d="M 2.546875,0 H 1.25 v -12.46875 h 1.296875 v 4.28125 c 0.925781,-0.445312 1.816406,-0.671875 2.671875,-0.671875 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.859375 V -4.546875 C 6.859375,-5.753906 6.738281,-6.578125 6.5,-7.015625 6.257812,-7.460938 5.757812,-7.6875 5,-7.6875 c -0.730469,0 -1.4375,0.132812 -2.125,0.390625 l -0.328125,0.125 z m 0,0"
+ id="path4974" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4988"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(177.4696,591.17926)"
+ id="g4986">
+ <g
+ id="g4984">
+ <path
+ d="m 0.875,-4.359375 c 0,-1.582031 0.28125,-2.726563 0.84375,-3.4375 0.5625,-0.707031 1.515625,-1.0625 2.859375,-1.0625 1.351563,0 2.3125,0.355469 2.875,1.0625 0.5625,0.710937 0.84375,1.855469 0.84375,3.4375 C 8.296875,-2.773438 8.03125,-1.625 7.5,-0.90625 6.96875,-0.1875 5.992188,0.171875 4.578125,0.171875 c -1.40625,0 -2.375,-0.359375 -2.90625,-1.078125 C 1.140625,-1.625 0.875,-2.773438 0.875,-4.359375 Z M 2.203125,-4.375 c 0,1.261719 0.148437,2.148438 0.453125,2.65625 0.3125,0.511719 0.957031,0.765625 1.9375,0.765625 0.976562,0 1.617188,-0.25 1.921875,-0.75 C 6.816406,-2.210938 6.96875,-3.101562 6.96875,-4.375 6.96875,-5.644531 6.796875,-6.519531 6.453125,-7 6.117188,-7.476562 5.5,-7.71875 4.59375,-7.71875 3.6875,-7.71875 3.0625,-7.476562 2.71875,-7 2.375,-6.519531 2.203125,-5.644531 2.203125,-4.375 Z m 0,0"
+ id="path4982" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g4996"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(186.63236,591.17926)"
+ id="g4994">
+ <g
+ id="g4992">
+ <path
+ d="M 2.546875,0 H 1.25 v -8.671875 h 1.28125 v 0.59375 c 0.9375,-0.519531 1.832031,-0.78125 2.6875,-0.78125 1.164062,0 1.945312,0.3125 2.34375,0.9375 0.394531,0.625 0.59375,1.742187 0.59375,3.34375 V 0 H 6.875 v -4.546875 c 0,-1.207031 -0.121094,-2.03125 -0.359375,-2.46875 C 6.273438,-7.460938 5.769531,-7.6875 5,-7.6875 c -0.375,0 -0.765625,0.058594 -1.171875,0.171875 -0.40625,0.105469 -0.726563,0.210937 -0.953125,0.3125 l -0.328125,0.15625 z m 0,0"
+ id="path4990" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5004"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(145.18979,615.43933)"
+ id="g5002">
+ <g
+ id="g5000">
+ <path
+ d="m 0.21875,-10.8125 v -1.203125 h 8.6875 V -10.8125 H 5.25 V 0 H 3.921875 v -10.8125 z m 0,0"
+ id="path4998" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5012"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(154.31784,615.43933)"
+ id="g5010">
+ <g
+ id="g5008">
+ <path
+ d="M 0.4375,-8.671875 H 1.734375 L 3.90625,-1.125 h 0.578125 l 2.1875,-7.546875 H 7.96875 L 4.359375,3.859375 H 3.0625 L 4.1875,0 H 2.90625 Z m 0,0"
+ id="path5006" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5020"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(162.69968,615.43933)"
+ id="g5018">
+ <g
+ id="g5016">
+ <path
+ d="M 1.25,3.859375 V -8.671875 H 2.53125 V -8.0625 c 0.882812,-0.53125 1.753906,-0.796875 2.609375,-0.796875 1.09375,0 1.890625,0.355469 2.390625,1.0625 0.5,0.699219 0.75,1.855469 0.75,3.46875 0,1.605469 -0.292969,2.757813 -0.875,3.453125 C 6.820312,-0.175781 5.851562,0.171875 4.5,0.171875 c -0.710938,0 -1.359375,-0.0625 -1.953125,-0.1875 v 3.875 z M 4.953125,-7.6875 c -0.355469,0 -0.730469,0.058594 -1.125,0.171875 C 3.429688,-7.398438 3.113281,-7.285156 2.875,-7.171875 L 2.546875,-7 v 5.859375 c 0.820313,0.125 1.445313,0.1875 1.875,0.1875 0.9375,0 1.59375,-0.265625 1.96875,-0.796875 0.382813,-0.53125 0.578125,-1.394531 0.578125,-2.59375 0,-1.207031 -0.171875,-2.066406 -0.515625,-2.578125 -0.34375,-0.507813 -0.84375,-0.765625 -1.5,-0.765625 z m 0,0"
+ id="path5014" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5028"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(171.84508,615.43933)"
+ id="g5026">
+ <g
+ id="g5024">
+ <path
+ d="m 7.15625,-1.078125 0.5,-0.046875 0.03125,1.015625 C 6.375,0.078125 5.25,0.171875 4.3125,0.171875 3.0625,0.171875 2.175781,-0.1875 1.65625,-0.90625 1.132812,-1.632812 0.875,-2.757812 0.875,-4.28125 c 0,-3.050781 1.207031,-4.578125 3.625,-4.578125 1.164062,0 2.035156,0.328125 2.609375,0.984375 0.582031,0.65625 0.875,1.683594 0.875,3.078125 l -0.0625,1 H 2.1875 c 0,0.960937 0.171875,1.671875 0.515625,2.140625 0.351563,0.460938 0.957031,0.6875 1.8125,0.6875 0.863281,0 1.742187,-0.035156 2.640625,-0.109375 z M 6.6875,-4.84375 c 0,-1.0625 -0.171875,-1.8125 -0.515625,-2.25 C 5.828125,-7.539062 5.269531,-7.765625 4.5,-7.765625 c -0.773438,0 -1.351562,0.234375 -1.734375,0.703125 -0.386719,0.460938 -0.585937,1.199219 -0.59375,2.21875 z m 0,0"
+ id="path5022" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5034"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(180.6087,615.43933)"
+ id="g5032">
+ <g
+ id="g5030" />
+ </g>
+ </g>
+ <g
+ fill="#fefeff"
+ fill-opacity="1"
+ id="g5042"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ transform="translate(184.42651,615.43933)"
+ id="g5040">
+ <g
+ id="g5038">
+ <path
+ d="m 1.25,-11.15625 c 1.082031,-0.320312 2.242188,-0.484375 3.484375,-0.484375 1.25,0 2.148437,0.242187 2.703125,0.71875 0.5625,0.46875 0.84375,1.226563 0.84375,2.265625 0,0.53125 -0.074219,0.917969 -0.21875,1.15625 -0.148438,0.230469 -0.261719,0.414062 -0.34375,0.546875 -0.085938,0.125 -0.199219,0.246094 -0.34375,0.359375 -0.25,0.199219 -0.453125,0.335938 -0.609375,0.40625 l -0.1875,0.125 c 0.675781,0.25 1.175781,0.5625 1.5,0.9375 0.320313,0.375 0.484375,0.992188 0.484375,1.84375 0,1.167969 -0.304688,2.039062 -0.90625,2.609375 -0.59375,0.5625 -1.53125,0.84375 -2.8125,0.84375 -1.023438,0 -2.101562,-0.1171875 -3.234375,-0.34375 l -0.53125,-0.125 0.125,-1.09375 C 2.453125,-1.128906 3.617188,-1 4.703125,-1 6.359375,-1.019531 7.1875,-1.765625 7.1875,-3.234375 c 0,-1.375 -0.789062,-2.085937 -2.359375,-2.140625 h -2.3125 v -1.15625 h 2.3125 c 0.488281,0 0.957031,-0.191406 1.40625,-0.578125 0.445313,-0.382813 0.671875,-0.894531 0.671875,-1.53125 0,-0.632813 -0.183594,-1.09375 -0.546875,-1.375 -0.355469,-0.289063 -0.953125,-0.4375 -1.796875,-0.4375 -0.929688,0 -1.839844,0.08984 -2.734375,0.265625 L 1.375,-10.109375 Z m 0,0"
+ id="path5036" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#12ef88673f)"
+ id="g5046"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1479)"
- d="M 111.125,196.45834 127,185.875"
- id="path1469"
- inkscape:connector-curvature="0" />
+ fill="#000000"
+ d="m 293.44922,366.47266 15.07422,-14.98829 -15.07422,-15.01171 -3.37891,3.36328 9.27344,9.26562 h -56.76953 v 4.76563 h 56.76953 l -9.27344,9.23828 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5044" />
+ </g>
+ <g
+ clip-path="url(#4425bd08fe)"
+ id="g5050"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1521)"
- d="M 111.125,217.625 127,201.75"
- id="path1511"
- inkscape:connector-curvature="0" />
+ fill="#000000"
+ d="m 554.83203,366.47266 15.07422,-14.98829 -15.07422,-15.01171 -3.38281,3.36328 9.27344,9.26562 h -56.76954 v 4.76563 h 56.76954 l -9.27344,9.23828 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5048" />
+ </g>
+ <g
+ clip-path="url(#29f410bb45)"
+ id="g5054"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1569)"
- d="m 195.79166,185.875 h 15.875"
- id="path1559"
- inkscape:connector-curvature="0" />
+ fill="#000000"
+ d="m 554.83203,542.04297 15.07422,-14.98438 -15.07422,-15.01562 -3.38281,3.36719 9.27344,9.26562 h -56.76954 v 4.76563 h 56.76954 l -9.27344,9.23828 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5052" />
+ </g>
+ <g
+ clip-path="url(#8612924f50)"
+ id="g5058"
+ transform="translate(-69.242111,-250.64609)">
<path
- style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1623)"
- d="m 195.79166,138.25001 h 15.875"
- id="path1613"
- inkscape:connector-curvature="0" />
+ fill="#000000"
+ d="m 287.44531,541.73437 15.07422,-14.98828 -15.07422,-15.01172 -3.3789,3.36329 9.26953,9.26562 h -56.76953 v 4.76953 h 56.76953 l -9.26953,9.23438 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5056" />
+ </g>
+ <g
+ clip-path="url(#9616827f5c)"
+ id="g5068"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ clip-path="url(#6d6215aef9)"
+ id="g5066">
+ <g
+ clip-path="url(#506e24dd3d)"
+ id="g5064">
+ <g
+ clip-path="url(#85c10bb5f0)"
+ id="g5062">
+ <path
+ fill="#000000"
+ d="m 279.46094,488.74609 19.99609,-7.21093 -7.32031,-19.98047 -4.48438,1.625 4.48828,12.3125 -51.44921,-23.98828 -2.01563,4.32031 51.44922,23.98828 -12.30469,4.45312 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5060" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#96382ab88a)"
+ id="g5078"
+ transform="translate(-69.242111,-250.64609)">
+ <g
+ clip-path="url(#8ee2f579d3)"
+ id="g5076">
+ <g
+ clip-path="url(#c24345751d)"
+ id="g5074">
+ <g
+ clip-path="url(#6c1dc82097)"
+ id="g5072">
+ <path
+ fill="#000000"
+ d="m 279.46094,565.48437 19.99609,7.21094 -7.32031,19.97656 -4.48438,-1.62109 4.48828,-12.31641 -51.44921,23.99219 -2.01563,-4.32031 51.44922,-23.99219 -12.30469,-4.44922 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path5070" />
+ </g>
+ </g>
+ </g>
</g>
</svg>
diff --git a/sources/shiboken6/doc/images/genrunnerarch.png b/sources/shiboken6/doc/images/genrunnerarch.png
deleted file mode 100644
index db1077cd0..000000000
--- a/sources/shiboken6/doc/images/genrunnerarch.png
+++ /dev/null
Binary files differ
diff --git a/sources/shiboken6/doc/images/genrunnerarch.svg b/sources/shiboken6/doc/images/genrunnerarch.svg
deleted file mode 100644
index ea7eb73e7..000000000
--- a/sources/shiboken6/doc/images/genrunnerarch.svg
+++ /dev/null
@@ -1,654 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="980"
- height="380"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.47pre4 r22446"
- version="1.0"
- sodipodi:docname="genrunnerarch.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="genrunnerarch.png"
- inkscape:export-xdpi="56.549999"
- inkscape:export-ydpi="56.549999">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="EmptyDiamondL"
- orient="auto"
- refY="0"
- refX="0"
- id="EmptyDiamondL"
- style="overflow:visible">
- <path
- id="path3930"
- d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="scale(0.8,0.8)" />
- </marker>
- <marker
- inkscape:stockid="EmptyTriangleInL"
- orient="auto"
- refY="0"
- refX="0"
- id="EmptyTriangleInL"
- style="overflow:visible">
- <path
- id="path3975"
- d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Sstart"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Sstart"
- style="overflow:visible">
- <path
- id="path3835"
- d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="matrix(0.2,0,0,0.2,1.2,0)" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Mend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Mend"
- style="overflow:visible">
- <path
- id="path3832"
- d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="matrix(-0.4,0,0,-0.4,-4,0)" />
- </marker>
- <marker
- inkscape:stockid="Tail"
- orient="auto"
- refY="0"
- refX="0"
- id="Tail"
- style="overflow:visible">
- <g
- id="g3859"
- transform="scale(-1.2,-1.2)">
- <path
- id="path3861"
- d="M -3.8048674,-3.9585227 0.54352094,0"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- <path
- id="path3863"
- d="M -1.2866832,-3.9585227 3.0617053,0"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- <path
- id="path3865"
- d="M 1.3053582,-3.9585227 5.6537466,0"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- <path
- id="path3867"
- d="M -3.8048674,4.1775838 0.54352094,0.21974226"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- <path
- id="path3869"
- d="M -1.2866832,4.1775838 3.0617053,0.21974226"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- <path
- id="path3871"
- d="M 1.3053582,4.1775838 5.6537466,0.21974226"
- style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
- </g>
- </marker>
- <marker
- inkscape:stockid="Arrow2Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow2Lend"
- style="overflow:visible">
- <path
- id="path3636"
- style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
- transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
- </marker>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- id="perspective10" />
- <inkscape:perspective
- id="perspective3033"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective3881"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective3915"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective3956"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective5100"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective5322"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective5365"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective5391"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <marker
- inkscape:stockid="EmptyTriangleInL"
- orient="auto"
- refY="0"
- refX="0"
- id="EmptyTriangleInL-4"
- style="overflow:visible">
- <path
- id="path3975-9"
- d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
- </marker>
- <inkscape:perspective
- id="perspective5621"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective5643"
- inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
- inkscape:vp_z="1 : 0.5 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 0.5 : 1"
- sodipodi:type="inkscape:persp3d" />
- <marker
- inkscape:stockid="EmptyDiamondL"
- orient="auto"
- refY="0"
- refX="0"
- id="EmptyDiamondL-7"
- style="overflow:visible">
- <path
- id="path3930-7"
- d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="scale(0.8,0.8)" />
- </marker>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.0716799"
- inkscape:cx="460.27913"
- inkscape:cy="148.01364"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1862"
- inkscape:window-height="1019"
- inkscape:window-x="20"
- inkscape:window-y="89"
- showguides="true"
- inkscape:guide-bbox="true"
- inkscape:window-maximized="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(472.44407,-697.53823)">
- <flowRoot
- xml:space="preserve"
- id="flowRoot3229"
- style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- transform="translate(2.0918751e-6,-6.0000008)"><flowRegion
- id="flowRegion3231"><rect
- id="rect3233"
- width="125.74072"
- height="40.5849"
- x="388.45547"
- y="279.5423" /></flowRegion><flowPara
- id="flowPara3235" /></flowRoot> <g
- id="g5867"
- transform="translate(6.7062969,-7.6922472)">
- <rect
- rx="3.4968286"
- ry="5.2462597"
- y="713.31403"
- x="-472.05276"
- height="363.61459"
- width="393.78473"
- id="rect3609"
- style="fill:#e4fae3;fill-opacity:0.65882353;stroke:#8eff89;stroke-width:0.78260708;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <text
- transform="scale(1.0000266,0.9999734)"
- id="text3601"
- y="742.43872"
- x="-275.16165"
- style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- id="tspan3605"
- style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
- y="742.43872"
- x="-275.16165"
- sodipodi:role="line"><tspan
- id="tspan2508"
- style="font-weight:bold">API Extractor</tspan></tspan></text>
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-587.62742,-106.48682)"
- id="g3763">
- <rect
- style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.79775763;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect3737"
- width="244.82956"
- height="101.59812"
- x="267.06232"
- y="905.13727"
- ry="3.1522403"
- rx="2.4096873" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="389.39117"
- y="931.86993"
- id="text3739"><tspan
- sodipodi:role="line"
- x="389.39117"
- y="931.86993"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
- id="tspan3741">ApiExtractor</tspan><tspan
- id="tspan2523"
- sodipodi:role="line"
- x="389.39117"
- y="953.38947"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">commands the parsing and</tspan><tspan
- id="tspan2517"
- sodipodi:role="line"
- x="389.39117"
- y="973.38947"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">building of the data model</tspan><tspan
- id="tspan2519"
- sodipodi:role="line"
- x="389.39117"
- y="993.38947"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and calls the user generators</tspan></text>
- </g>
- <rect
- rx="2.1814992"
- ry="5.2485871"
- y="713.45312"
- x="219.72128"
- height="363.77597"
- width="274.11292"
- id="rect9190"
- style="fill:#b8d1f1;fill-opacity:0.51184836;stroke:#0045a4;stroke-width:0.6182732;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <text
- transform="scale(1.0000266,0.9999734)"
- id="text9192"
- y="742.66901"
- x="357.65579"
- style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#002e7a;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- id="tspan9194"
- style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002e7a;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
- y="742.66901"
- x="357.65579"
- sodipodi:role="line"><tspan
- id="tspan2512"
- style="font-weight:bold;fill:#002e7a;fill-opacity:1">front-end</tspan><tspan
- id="tspan2514"
- style="font-size:22px;fill:#002e7a;fill-opacity:1" /></tspan></text>
- <rect
- rx="2.2192271"
- ry="5.2485123"
- y="713.23639"
- x="-68.659073"
- height="363.77075"
- width="278.85358"
- id="rect9190-9"
- style="fill:#cbe990;fill-opacity:0.51184836;stroke:#6ca400;stroke-width:0.62359226;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <text
- transform="scale(1.0000266,0.9999734)"
- id="text9192-3"
- y="741.71094"
- x="70.291061"
- style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- id="tspan9194-7"
- style="font-size:26px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
- y="741.71094"
- x="70.291061"
- sodipodi:role="line">Generator Runner</tspan></text>
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-687.04869,-241.74888)"
- id="g9234-4">
- <rect
- style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.73640609;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect9206-4"
- width="218.17299"
- height="83.517967"
- x="694.6994"
- y="1044.8701"
- ry="2.5912752"
- rx="2.4978092" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="803.78589"
- y="1072.3693"
- id="text9208-3"><tspan
- sodipodi:role="line"
- x="803.78589"
- y="1072.3693"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
- id="tspan9210-0">Generator</tspan><tspan
- id="tspan9222-8"
- sodipodi:role="line"
- x="803.78589"
- y="1093.8888"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">base class for front-end</tspan><tspan
- id="tspan3946"
- sodipodi:role="line"
- x="803.78589"
- y="1113.8888"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">output classes</tspan></text>
- </g>
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-726.09128,-46.791689)"
- id="g10497-6">
- <rect
- style="fill:#89b3e7;fill-opacity:1;stroke:#0049a4;stroke-width:1.04736876;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect10444-8"
- width="256.05252"
- height="143.95157"
- x="990.81482"
- y="843.58032"
- ry="4.4663219"
- rx="2.9314826" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="1118.0945"
- y="873.04047"
- id="text10446-8"><tspan
- sodipodi:role="line"
- x="1118.0945"
- y="873.04047"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
- id="tspan10448-4">SpecificGenerator</tspan><tspan
- id="tspan4063"
- sodipodi:role="line"
- x="1118.0945"
- y="894.56"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">generators written for any</tspan><tspan
- id="tspan5381"
- sodipodi:role="line"
- x="1118.0945"
- y="914.56"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">desired output,</tspan><tspan
- id="tspan4065"
- sodipodi:role="line"
- x="1118.0945"
- y="934.56"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"> e.g.: HppGenerator,</tspan><tspan
- id="tspan4071"
- sodipodi:role="line"
- x="1118.0945"
- y="954.56"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">CppGenerator,</tspan><tspan
- id="tspan4073"
- sodipodi:role="line"
- x="1118.0945"
- y="974.56"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">ConverterGenerator</tspan></text>
- </g>
- <path
- sodipodi:nodetypes="cc"
- transform="translate(109.91989,748.26874)"
- id="path4056"
- d="m -201.98482,41.728896 76.97065,5e-6"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
- <path
- sodipodi:nodetypes="cc"
- id="path4056-2"
- d="m 197.04022,787.89746 35.38656,0"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-start:url(#EmptyTriangleInL)" />
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-1010.4541,91.401187)"
- id="g10497">
- <rect
- style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.88060772;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect10444"
- width="256.21927"
- height="101.69494"
- x="990.73145"
- y="843.49695"
- ry="3.1552441"
- rx="2.9333918" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="1012.22"
- y="870.08466"
- id="text10446"><tspan
- sodipodi:role="line"
- x="1012.22"
- y="870.08466"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
- id="tspan10448">Generator App</tspan><tspan
- id="tspan10456"
- sodipodi:role="line"
- x="1012.22"
- y="891.60419"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* loads generators</tspan><tspan
- id="tspan5353"
- sodipodi:role="line"
- x="1012.22"
- y="911.60419"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* setup API Extractor</tspan><tspan
- id="tspan5355"
- sodipodi:role="line"
- x="1012.22"
- y="931.60419"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* executes each generator</tspan></text>
- </g>
- <path
- sodipodi:nodetypes="cc"
- id="path4056-9"
- d="m 72.409302,850.57374 0,56.99122"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
- <path
- sodipodi:nodetypes="ccc"
- id="path4056-2-0"
- d="m -86.437722,825.54499 52.188784,0 0.06367,81.67009"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-start:url(#EmptyDiamondL)" />
- <path
- sodipodi:nodetypes="cc"
- id="path4056-91"
- d="m -394.83596,853.70064 0,121.42437"
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-707.18032,-153.53291)"
- id="g3809">
- <rect
- style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:1.00168562;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect3785"
- width="332.48172"
- height="82.830231"
- x="302.83319"
- y="1068.9153"
- ry="3.1461167"
- rx="3.8065021" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="469.03497"
- y="1095.5493"
- id="text3787"><tspan
- id="tspan3791"
- sodipodi:role="line"
- x="469.03497"
- y="1095.5493"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">AbstractMetaBuilder</tspan><tspan
- sodipodi:role="line"
- x="469.03497"
- y="1117.0688"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
- id="tspan3807">builds the data model with information</tspan><tspan
- id="tspan2545"
- sodipodi:role="line"
- x="469.03497"
- y="1137.0688"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">from headers and binding directives</tspan><tspan
- id="tspan3795"
- sodipodi:role="line"
- x="469.03497"
- y="1157.0688"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" /></text>
- </g>
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-755.89347,194.37862)"
- id="g3709">
- <rect
- style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.69825613;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect2821"
- width="198.90968"
- height="93.892342"
- x="305.2475"
- y="807.38849"
- ry="2.6812849"
- rx="2.1703238" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="405.17499"
- y="831.81903"
- id="text3611"><tspan
- id="tspan3687"
- sodipodi:role="line"
- x="405.17499"
- y="831.81903"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">TypeDatabase</tspan><tspan
- id="tspan5641"
- sodipodi:role="line"
- x="405.17499"
- y="853.33856"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses typesystem</tspan><tspan
- id="tspan3689"
- sodipodi:role="line"
- x="405.17499"
- y="873.33856"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and stores information</tspan></text>
- </g>
- <g
- transform="matrix(0.9678438,0,0,0.9677923,-589.50555,-13.923919)"
- id="g3728">
- <rect
- style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.54871088;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="rect3625"
- width="117.15066"
- height="86.355225"
- x="133.25664"
- y="809.36938"
- ry="2.6793056"
- rx="1.3412292" />
- <text
- xml:space="preserve"
- style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
- x="191.58197"
- y="838.75159"
- id="text3627"><tspan
- sodipodi:role="line"
- x="191.58197"
- y="838.75159"
- style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
- id="tspan3631">Parser</tspan><tspan
- id="tspan3695"
- sodipodi:role="line"
- x="191.58197"
- y="860.27112"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses the</tspan><tspan
- id="tspan3697"
- sodipodi:role="line"
- x="191.58197"
- y="880.27112"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">lib headers</tspan></text>
- </g>
- <path
- sodipodi:nodetypes="ccc"
- id="path4056-2-0-1"
- d="m 197.39006,961.71122 158.27877,0 0.19429,-51.88885"
- style="fill:none;stroke:#000000;stroke-width:1.38812411;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8.32874408, 1.38812401;stroke-dashoffset:0;marker-start:none" />
- </g>
- </g>
-</svg>
diff --git a/sources/shiboken6/doc/images/qtforpython-underthehood.png b/sources/shiboken6/doc/images/qtforpython-underthehood.png
index 64e30b1c5..295cefcf9 100644
--- a/sources/shiboken6/doc/images/qtforpython-underthehood.png
+++ b/sources/shiboken6/doc/images/qtforpython-underthehood.png
Binary files differ
diff --git a/sources/shiboken6/doc/images/qtforpython-underthehood.svg b/sources/shiboken6/doc/images/qtforpython-underthehood.svg
new file mode 100644
index 000000000..8924d9d4b
--- /dev/null
+++ b/sources/shiboken6/doc/images/qtforpython-underthehood.svg
@@ -0,0 +1,1502 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="972.87427"
+ zoomAndPan="magnify"
+ viewBox="0 0 729.6557 410.72465"
+ height="547.63287"
+ preserveAspectRatio="xMidYMid"
+ version="1.0"
+ id="svg684"
+ sodipodi:docname="qtforpython-underthehood.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ inkscape:export-filename="qtforpython-underthehood.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview686"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="0.80648148"
+ inkscape:cx="400.50517"
+ inkscape:cy="272.16992"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg684" />
+ <defs
+ id="defs94">
+ <filter
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="941f55d5ad">
+ <feColorMatrix
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
+ color-interpolation-filters="sRGB"
+ id="feColorMatrix2" />
+ </filter>
+ <filter
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="7900779894">
+ <feColorMatrix
+ values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.2126 0.7152 0.0722 0 0"
+ color-interpolation-filters="sRGB"
+ id="feColorMatrix5" />
+ </filter>
+ <clipPath
+ id="43b70e6d50">
+ <path
+ d="m 329.69531,337.88281 h 134.25 v 134.25 h -134.25 z m 0,0"
+ clip-rule="nonzero"
+ id="path10" />
+ </clipPath>
+ <clipPath
+ id="5e0498f898">
+ <path
+ d="m 418.84375,430.04687 h 78 v 78 h -78 z m 0,0"
+ clip-rule="nonzero"
+ id="path13" />
+ </clipPath>
+ <clipPath
+ id="ee2fc7472f">
+ <path
+ d="m 296.76953,430.04687 h 77.87109 v 78 h -77.87109 z m 0,0"
+ clip-rule="nonzero"
+ id="path16" />
+ </clipPath>
+ <clipPath
+ id="e49c99af70">
+ <path
+ d="m 418.84375,307.19531 h 78 v 77.8711 h -78 z m 0,0"
+ clip-rule="nonzero"
+ id="path19" />
+ </clipPath>
+ <clipPath
+ id="9f18cca9db">
+ <path
+ d="m 296.76953,307.19531 h 77.87109 v 77.8711 h -77.87109 z m 0,0"
+ clip-rule="nonzero"
+ id="path22" />
+ </clipPath>
+ <clipPath
+ id="9c58565a54">
+ <path
+ d="m 240.875,207.47656 h 111.52734 v 82.5 H 240.875 Z m 0,0"
+ clip-rule="nonzero"
+ id="path25" />
+ </clipPath>
+ <clipPath
+ id="9d28a89d3d">
+ <path
+ d="m 46.855469,529 h 73.500001 v 30 H 46.855469 Z m 0,0"
+ clip-rule="nonzero"
+ id="path28" />
+ </clipPath>
+ <clipPath
+ id="0baef73a1e">
+ <path
+ d="m 163.94922,224.44922 h 69.75 v 72 h -69.75 z m 0,0"
+ clip-rule="nonzero"
+ id="path31" />
+ </clipPath>
+ <clipPath
+ id="1f4a27800a">
+ <path
+ d="M 62.34375,227.08203 H 153 V 293 H 62.34375 Z m 0,0"
+ clip-rule="nonzero"
+ id="path34" />
+ </clipPath>
+ <mask
+ id="e94e818b4b">
+ <g
+ filter="url(#941f55d5ad)"
+ id="g42">
+ <g
+ filter="url(#7900779894)"
+ transform="matrix(0.196004,0,0,0.194118,62.344152,227.08093)"
+ id="g40">
+ <image
+ x="0"
+ y="0"
+ width="463"
+ xlink:href="data:image/png;base64,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"
+ height="340"
+ preserveAspectRatio="xMidYMid"
+ id="image38" />
+ </g>
+ </g>
+ </mask>
+ <mask
+ id="8f2a27f6f4">
+ <g
+ filter="url(#941f55d5ad)"
+ id="g51">
+ <g
+ filter="url(#7900779894)"
+ transform="matrix(0.198482,0,0,0.198482,536.61425,471.98102)"
+ id="g49">
+ <image
+ x="0"
+ y="0"
+ width="461"
+ xlink:href="data:image/png;base64,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"
+ height="461"
+ preserveAspectRatio="xMidYMid"
+ id="image47" />
+ </g>
+ </g>
+ </mask>
+ <clipPath
+ id="9cd47c7ee3">
+ <path
+ d="m 268,534 h 119 v 74 H 268 Z m 0,0"
+ clip-rule="nonzero"
+ id="path55" />
+ </clipPath>
+ <clipPath
+ id="69785d3302">
+ <path
+ d="m 284.80469,510.52344 111.6914,32.23828 -23.91797,82.86719 -111.6914,-32.23829 z m 0,0"
+ clip-rule="nonzero"
+ id="path58" />
+ </clipPath>
+ <clipPath
+ id="9c0953b9a2">
+ <path
+ d="m 372.87891,625.72656 -111.69141,-32.23437 23.91797,-82.8711 111.6914,32.23828 z m 0,0"
+ clip-rule="nonzero"
+ id="path61" />
+ </clipPath>
+ <clipPath
+ id="8e32f12866">
+ <path
+ d="m 372.87891,625.72656 -111.69141,-32.23437 23.91797,-82.8711 111.6914,32.23828 z m 0,0"
+ clip-rule="nonzero"
+ id="path64" />
+ </clipPath>
+ <clipPath
+ id="a3af3eb6b6">
+ <path
+ d="m 698.37109,329 h 48.75 v 135.9375 h -48.75 z m 0,0"
+ clip-rule="nonzero"
+ id="path67" />
+ </clipPath>
+ <clipPath
+ id="31f8f05393">
+ <path
+ d="m 508,316 h 77 v 50 h -77 z m 0,0"
+ clip-rule="nonzero"
+ id="path70" />
+ </clipPath>
+ <clipPath
+ id="41889181af">
+ <path
+ d="M 594.73828,339.63672 520.52344,380.56641 506.03516,354.29687 580.25,313.36719 Z m 0,0"
+ clip-rule="nonzero"
+ id="path73" />
+ </clipPath>
+ <clipPath
+ id="fe9d13e8b4">
+ <path
+ d="m 520.6875,380.47656 74.21484,-40.92969 -14.48828,-26.26953 -74.21094,40.92969 z m 0,0"
+ clip-rule="nonzero"
+ id="path76" />
+ </clipPath>
+ <clipPath
+ id="6c6e35ef02">
+ <path
+ d="m 520.6875,380.47656 74.21484,-40.92969 -14.48828,-26.26953 -74.21094,40.92969 z m 0,0"
+ clip-rule="nonzero"
+ id="path79" />
+ </clipPath>
+ <clipPath
+ id="9d2f7452d2">
+ <path
+ d="m 544,250 h 60.1875 v 43.51172 H 544 Z m 0,0"
+ clip-rule="nonzero"
+ id="path82" />
+ </clipPath>
+ <clipPath
+ id="5d999a0038">
+ <path
+ d="M 543.4375,219 H 560 v 8 h -16.5625 z m 0,0"
+ clip-rule="nonzero"
+ id="path85" />
+ </clipPath>
+ <clipPath
+ id="a4f0b4e13e">
+ <path
+ d="m 548,215.51172 h 47 V 249 h -47 z m 0,0"
+ clip-rule="nonzero"
+ id="path88" />
+ </clipPath>
+ <clipPath
+ id="0ea259bc34">
+ <path
+ d="m 595,215.51172 h 6 V 249 h -6 z m 0,0"
+ clip-rule="nonzero"
+ id="path91" />
+ </clipPath>
+ </defs>
+ <rect
+ style="fill:#ffffff;stroke:none;stroke-width:0.75"
+ id="rect1721"
+ width="728.9057"
+ height="409.97464"
+ x="0.375"
+ y="0.375" />
+ <path
+ fill="#41cb51"
+ d="m 353.33158,222.2777 c -10.36328,0 -18.79687,-8.4336 -18.79687,-18.79688 0,-10.36328 8.43359,-18.79297 18.79687,-18.79297 10.35938,0 18.79297,8.42969 18.79297,18.79297 0,10.36328 -8.43359,18.79688 -18.79297,18.79688 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path102" />
+ <g
+ clip-path="url(#43b70e6d50)"
+ id="g106"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#41cb51"
+ d="m 461.69141,394.18359 -14.32813,-2.33984 c -1.21484,-4.66797 -3.07422,-9.12891 -5.54687,-13.3125 l 8.37109,-11.92969 c 0.75,-1.07031 0.625,-2.51953 -0.29688,-3.4414 L 438.5,351.76953 c -0.92969,-0.93359 -2.40234,-1.05078 -3.46484,-0.28125 l -11.80469,8.48438 c -4.19141,-2.46485 -8.66016,-4.32032 -13.32422,-5.52735 l -2.51172,-14.33984 c -0.22656,-1.28516 -1.34375,-2.22266 -2.64844,-2.22266 h -16.10937 c -1.31641,0 -2.4375,0.95313 -2.65235,2.25391 l -2.33984,14.33984 c -4.60937,1.19922 -9.03516,3.03516 -13.19531,5.47656 l -11.86328,-8.47656 c -1.07032,-0.76172 -2.52735,-0.64062 -3.46094,0.28516 l -11.39063,11.39062 c -0.92187,0.91797 -1.05078,2.36719 -0.30078,3.4336 l 8.375,11.96484 c -2.46093,4.16406 -4.30859,8.60938 -5.51953,13.24609 l -14.34765,2.39063 c -1.29688,0.21484 -2.2461,1.33203 -2.2461,2.64453 v 16.11328 c 0,1.30078 0.9336,2.41406 2.21485,2.64063 l 14.35156,2.54687 c 1.20312,4.62891 3.04297,9.06641 5.49219,13.24219 l -8.48047,11.85156 c -0.76172,1.07031 -0.64063,2.53516 0.28515,3.46094 l 11.39063,11.39062 c 0.91797,0.91797 2.36719,1.04688 3.4375,0.30079 l 11.95703,-8.36719 c 4.14844,2.45312 8.58984,4.30078 13.24609,5.51953 l 2.39453,14.35937 c 0.21875,1.29297 1.33985,2.24219 2.65235,2.24219 h 16.10937 c 1.29688,0 2.41407,-0.93359 2.64063,-2.21484 l 2.54687,-14.35547 c 4.69141,-1.21484 9.17578,-3.07813 13.3711,-5.55469 l 11.9414,8.3711 c 1.07032,0.75 2.51953,0.625 3.44141,-0.29688 l 11.38281,-11.39062 c 0.9336,-0.92969 1.05078,-2.39844 0.28125,-3.46485 l -8.49219,-11.80469 c 2.46094,-4.1875 4.3125,-8.65234 5.51954,-13.3164 l 14.34375,-2.51563 c 1.28515,-0.22656 2.22265,-1.34375 2.22265,-2.64453 v -16.11328 c 0,-1.3125 -0.95312,-2.4375 -2.2539,-2.64844 z m -64.8711,43.04688 c -17.76953,0 -32.22265,-14.45703 -32.22265,-32.22266 0,-17.76562 14.45312,-32.21875 32.22265,-32.21875 17.76563,0 32.21875,14.45313 32.21875,32.21875 0,17.76563 -14.45312,32.22266 -32.21875,32.22266 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path104" />
+ </g>
+ <g
+ clip-path="url(#5e0498f898)"
+ id="g110"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#ffd43b"
+ d="m 473.52344,430.04687 c 0,30.17188 -24.50782,54.67969 -54.67969,54.67969 v 23.32031 c 43.08594,0 78,-34.91406 78,-78 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path108" />
+ </g>
+ <g
+ clip-path="url(#ee2fc7472f)"
+ id="g114"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#306998"
+ d="m 320.08984,430.04687 c 0,30.17188 24.50391,54.67969 54.67969,54.67969 v 23.32031 c -43.08594,0 -78,-34.91406 -78,-78 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path112" />
+ </g>
+ <g
+ clip-path="url(#e49c99af70)"
+ id="g118"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#306998"
+ d="m 473.52344,385.19531 c 0,-30.17187 -24.50782,-54.67969 -54.67969,-54.67969 v -23.32031 c 43.08594,0 78,34.91406 78,78 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path116" />
+ </g>
+ <g
+ clip-path="url(#9f18cca9db)"
+ id="g122"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#ffd43b"
+ d="m 320.08984,385.19531 c 0,-30.17187 24.50391,-54.67969 54.67969,-54.67969 v -23.32031 c -43.08594,0 -78,34.91406 -78,78 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path120" />
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g130"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(618.829,252.49077)"
+ id="g128">
+ <g
+ id="g126">
+ <path
+ d="m 10.484375,0.375 c -3.398437,0 -5.699219,-0.9375 -6.90625,-2.8125 -1.210937,-1.882812 -1.8125,-4.972656 -1.8125,-9.265625 0,-4.289063 0.609375,-7.347656 1.828125,-9.171875 1.21875,-1.820312 3.515625,-2.734375 6.890625,-2.734375 2.007813,0 4.222656,0.28125 6.640625,0.84375 L 17,-19.703125 C 14.957031,-20.066406 12.921875,-20.25 10.890625,-20.25 c -2.03125,0 -3.414063,0.605469 -4.140625,1.8125 -0.71875,1.210938 -1.078125,3.484375 -1.078125,6.828125 0,3.335937 0.347656,5.605469 1.046875,6.8125 0.695312,1.210937 2.0625,1.8125 4.09375,1.8125 2.039062,0 4.101562,-0.171875 6.1875,-0.515625 l 0.09375,3.125 c -2.324219,0.5 -4.527344,0.75 -6.609375,0.75 z m 0,0"
+ id="path124" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g138"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(636.53192,252.49077)"
+ id="g136">
+ <g
+ id="g134">
+ <path
+ d="m 11.1875,-7.21875 h -4.75 V 0 h -3.75 v -23.234375 h 8.5 c 5.269531,0 7.90625,2.601563 7.90625,7.796875 0,2.667969 -0.664062,4.703125 -1.984375,6.109375 -1.324219,1.40625 -3.296875,2.109375 -5.921875,2.109375 z m -4.75,-3.265625 h 4.71875 c 2.71875,0 4.078125,-1.648437 4.078125,-4.953125 0,-1.582031 -0.328125,-2.734375 -0.984375,-3.453125 -0.65625,-0.726563 -1.6875,-1.09375 -3.09375,-1.09375 H 6.4375 Z m 0,0"
+ id="path132" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g146"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(655.82879,252.49077)"
+ id="g144">
+ <g
+ id="g142">
+ <path
+ d="M 0.671875,-16.96875 H 4.3125 l 3.59375,13.8125 H 8.8125 l 3.609375,-13.8125 h 3.65625 L 9.640625,7.296875 H 6 L 8.046875,0 H 5.125 Z m 0,0"
+ id="path140" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g154"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(671.76817,252.49077)"
+ id="g152">
+ <g
+ id="g150">
+ <path
+ d="M 11.359375,-13.8125 H 6.6875 v 7.46875 c 0,1.375 0.097656,2.292969 0.296875,2.75 0.207031,0.449219 0.726563,0.671875 1.5625,0.671875 l 2.78125,-0.09375 L 11.5,-0.0625 C 9.988281,0.226562 8.835938,0.375 8.046875,0.375 c -1.929687,0 -3.25,-0.4375 -3.96875,-1.3125 -0.710937,-0.882812 -1.0625,-2.550781 -1.0625,-5 v -7.875 H 0.84375 v -3.15625 H 3.015625 V -21.875 H 6.6875 v 4.90625 h 4.671875 z m 0,0"
+ id="path148" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g162"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(683.16307,252.49077)"
+ id="g160">
+ <g
+ id="g158">
+ <path
+ d="M 5.9375,0 H 2.234375 V -24.015625 H 5.9375 v 7.9375 c 1.675781,-0.832031 3.222656,-1.25 4.640625,-1.25 2.257813,0 3.800781,0.640625 4.625,1.921875 0.832031,1.273438 1.25,3.375 1.25,6.3125 V 0 H 12.75 v -8.984375 c 0,-1.832031 -0.195312,-3.132813 -0.578125,-3.90625 -0.386719,-0.769531 -1.199219,-1.15625 -2.4375,-1.15625 -1.085937,0 -2.167969,0.183594 -3.25,0.546875 L 5.9375,-13.296875 Z m 0,0"
+ id="path156" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g170"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(700.9338,252.49077)"
+ id="g168">
+ <g
+ id="g166">
+ <path
+ d="m 3.171875,-15.125 c 1.164063,-1.46875 3.101563,-2.203125 5.8125,-2.203125 2.71875,0 4.65625,0.734375 5.8125,2.203125 1.164063,1.46875 1.75,3.671875 1.75,6.609375 0,2.9375 -0.570313,5.15625 -1.703125,6.65625 -1.125,1.492187 -3.078125,2.234375 -5.859375,2.234375 -2.78125,0 -4.742187,-0.742188 -5.875,-2.234375 -1.125,-1.5 -1.6875,-3.71875 -1.6875,-6.65625 0,-2.9375 0.582031,-5.140625 1.75,-6.609375 z M 5.9375,-4.109375 C 6.457031,-3.203125 7.472656,-2.75 8.984375,-2.75 c 1.519531,0 2.539063,-0.453125 3.0625,-1.359375 0.519531,-0.90625 0.78125,-2.382813 0.78125,-4.4375 0,-2.0625 -0.28125,-3.519531 -0.84375,-4.375 -0.554687,-0.863281 -1.554687,-1.296875 -3,-1.296875 -1.449219,0 -2.449219,0.433594 -3,1.296875 -0.554687,0.855469 -0.828125,2.3125 -0.828125,4.375 0,2.054687 0.257812,3.53125 0.78125,4.4375 z m 0,0"
+ id="path164" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g178"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(718.16191,252.49077)"
+ id="g176">
+ <g
+ id="g174">
+ <path
+ d="M 5.9375,0 H 2.234375 V -16.96875 H 5.90625 v 1.0625 c 1.644531,-0.945312 3.203125,-1.421875 4.671875,-1.421875 2.257813,0 3.800781,0.640625 4.625,1.921875 0.832031,1.273438 1.25,3.375 1.25,6.3125 V 0 H 12.78125 v -8.984375 c 0,-1.832031 -0.199219,-3.132813 -0.59375,-3.90625 -0.398438,-0.769531 -1.203125,-1.15625 -2.421875,-1.15625 -1.148437,0 -2.257813,0.230469 -3.328125,0.6875 l -0.5,0.203125 z m 0,0"
+ id="path172" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g186"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(618.829,286.99077)"
+ id="g184">
+ <g
+ id="g182">
+ <path
+ d="m 2.6875,0 v -23.234375 h 14.640625 v 3.28125 H 6.4375 v 6.59375 h 8.859375 v 3.25 H 6.4375 v 6.78125 H 17.328125 V 0 Z m 0,0"
+ id="path180" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g194"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(636.83714,286.99077)"
+ id="g192">
+ <g
+ id="g190">
+ <path
+ d="m 0.609375,-16.96875 h 3.9375 l 3.328125,5.875 3.359375,-5.875 H 15.15625 L 10.109375,-8.609375 15.15625,0 H 11.234375 L 7.875,-5.796875 4.546875,0 h -3.9375 L 5.53125,-8.515625 Z m 0,0"
+ id="path188" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g202"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(651.82693,286.99077)"
+ id="g200">
+ <g
+ id="g198">
+ <path
+ d="M 11.359375,-13.8125 H 6.6875 v 7.46875 c 0,1.375 0.097656,2.292969 0.296875,2.75 0.207031,0.449219 0.726563,0.671875 1.5625,0.671875 l 2.78125,-0.09375 L 11.5,-0.0625 C 9.988281,0.226562 8.835938,0.375 8.046875,0.375 c -1.929687,0 -3.25,-0.4375 -3.96875,-1.3125 -0.710937,-0.882812 -1.0625,-2.550781 -1.0625,-5 v -7.875 H 0.84375 v -3.15625 H 3.015625 V -21.875 H 6.6875 v 4.90625 h 4.671875 z m 0,0"
+ id="path196" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g210"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(663.22182,286.99077)"
+ id="g208">
+ <g
+ id="g206">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path204" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g218"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(679.70382,286.99077)"
+ id="g216">
+ <g
+ id="g214">
+ <path
+ d="M 5.9375,0 H 2.234375 V -16.96875 H 5.90625 v 1.0625 c 1.644531,-0.945312 3.203125,-1.421875 4.671875,-1.421875 2.257813,0 3.800781,0.640625 4.625,1.921875 0.832031,1.273438 1.25,3.375 1.25,6.3125 V 0 H 12.78125 v -8.984375 c 0,-1.832031 -0.199219,-3.132813 -0.59375,-3.90625 -0.398438,-0.769531 -1.203125,-1.15625 -2.421875,-1.15625 -1.148437,0 -2.257813,0.230469 -3.328125,0.6875 l -0.5,0.203125 z m 0,0"
+ id="path212" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g226"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(697.47455,286.99077)"
+ id="g224">
+ <g
+ id="g222">
+ <path
+ d="m 14.015625,-13.46875 c -2.679687,-0.363281 -4.617187,-0.546875 -5.8125,-0.546875 -1.199219,0 -2.03125,0.148437 -2.5,0.4375 -0.460937,0.28125 -0.6875,0.730469 -0.6875,1.34375 0,0.605469 0.253906,1.03125 0.765625,1.28125 0.507812,0.25 1.707031,0.542969 3.59375,0.875 1.894531,0.324219 3.238281,0.835937 4.03125,1.53125 0.789062,0.699219 1.1875,1.945313 1.1875,3.734375 0,1.78125 -0.574219,3.09375 -1.71875,3.9375 -1.148438,0.8359375 -2.8125,1.25 -5,1.25 -1.386719,0 -3.132812,-0.195312 -5.234375,-0.578125 L 1.59375,-0.375 1.734375,-3.453125 c 2.707031,0.355469 4.660156,0.53125 5.859375,0.53125 1.195312,0 2.050781,-0.144531 2.5625,-0.4375 0.507812,-0.289063 0.765625,-0.773437 0.765625,-1.453125 0,-0.675781 -0.246094,-1.144531 -0.734375,-1.40625 C 9.707031,-6.476562 8.546875,-6.757812 6.703125,-7.0625 4.859375,-7.375 3.503906,-7.859375 2.640625,-8.515625 c -0.855469,-0.65625 -1.28125,-1.851563 -1.28125,-3.59375 0,-1.738281 0.59375,-3.035156 1.78125,-3.890625 1.1875,-0.863281 2.707031,-1.296875 4.5625,-1.296875 1.445313,0 3.222656,0.183594 5.328125,0.546875 l 1.046875,0.203125 z m 0,0"
+ id="path220" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g234"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(712.63391,286.99077)"
+ id="g232">
+ <g
+ id="g230">
+ <path
+ d="M 2.234375,0 V -16.96875 H 5.9375 V 0 Z m 0,-19.84375 V -23.75 H 5.9375 v 3.90625 z m 0,0"
+ id="path228" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g242"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(720.06086,286.99077)"
+ id="g240">
+ <g
+ id="g238">
+ <path
+ d="m 3.171875,-15.125 c 1.164063,-1.46875 3.101563,-2.203125 5.8125,-2.203125 2.71875,0 4.65625,0.734375 5.8125,2.203125 1.164063,1.46875 1.75,3.671875 1.75,6.609375 0,2.9375 -0.570313,5.15625 -1.703125,6.65625 -1.125,1.492187 -3.078125,2.234375 -5.859375,2.234375 -2.78125,0 -4.742187,-0.742188 -5.875,-2.234375 -1.125,-1.5 -1.6875,-3.71875 -1.6875,-6.65625 0,-2.9375 0.582031,-5.140625 1.75,-6.609375 z M 5.9375,-4.109375 C 6.457031,-3.203125 7.472656,-2.75 8.984375,-2.75 c 1.519531,0 2.539063,-0.453125 3.0625,-1.359375 0.519531,-0.90625 0.78125,-2.382813 0.78125,-4.4375 0,-2.0625 -0.28125,-3.519531 -0.84375,-4.375 -0.554687,-0.863281 -1.554687,-1.296875 -3,-1.296875 -1.449219,0 -2.449219,0.433594 -3,1.296875 -0.554687,0.855469 -0.828125,2.3125 -0.828125,4.375 0,2.054687 0.257812,3.53125 0.78125,4.4375 z m 0,0"
+ id="path236" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g250"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(737.28897,286.99077)"
+ id="g248">
+ <g
+ id="g246">
+ <path
+ d="M 5.9375,0 H 2.234375 V -16.96875 H 5.90625 v 1.0625 c 1.644531,-0.945312 3.203125,-1.421875 4.671875,-1.421875 2.257813,0 3.800781,0.640625 4.625,1.921875 0.832031,1.273438 1.25,3.375 1.25,6.3125 V 0 H 12.78125 v -8.984375 c 0,-1.832031 -0.199219,-3.132813 -0.59375,-3.90625 -0.398438,-0.769531 -1.203125,-1.15625 -2.421875,-1.15625 -1.148437,0 -2.257813,0.230469 -3.328125,0.6875 l -0.5,0.203125 z m 0,0"
+ id="path244" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#9c58565a54)"
+ id="g254"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 321.85156,262.05469 c -0.89844,-1.01172 -1.60547,-1.91016 -2.41406,-2.70703 -2.69531,-2.64454 -5.30078,-5.39844 -8.1875,-7.82422 -3.11328,-2.61719 -7.58984,-1.91016 -10.45703,1.125 -0.71485,0.75 -1.97656,0.98437 -3.11328,1.51172 -0.48828,1.21093 0.67187,1.74609 1.39062,2.42578 6.50781,6.16797 11.5625,13.44922 15.94531,21.17187 1.67969,2.95313 2.80469,6.23047 4.07813,9.40235 0.99609,2.48828 1.125,2.84375 3.84766,2.625 4.85546,-0.39063 9.08593,-2.03907 12.14453,-6.20313 5.32812,-7.23437 11.07422,-14.17187 15.0664,-22.29687 0.64453,-1.32032 1.125,-2.72657 2.01563,-4.89844 -3.98438,0.71484 -7.26172,0.6875 -9.36719,3.84765 -1.28906,1.9375 -2.60547,3.85157 -4.38281,6.4961 -0.45703,-2.78125 -0.73828,-4.70313 -1.08203,-6.60547 -2.60547,-14.33203 -8.38672,-27.26563 -19.23438,-37.11719 -9.86719,-8.97656 -21.45703,-15.17969 -35.35156,-15.35156 -11.67188,-0.13672 -21.69531,4.42969 -30.45313,11.76562 -3.5039,2.94141 -6.47265,6.53516 -9.58593,9.92188 -0.8086,0.87891 -1.25,2.07422 -1.85938,3.13672 0.23438,0.22656 0.47266,0.45312 0.70703,0.67578 1.4336,-0.88672 2.92188,-1.69922 4.27735,-2.69531 0.84375,-0.625 1.49609,-1.51563 2.20312,-2.3125 9.07813,-10.24219 20.54297,-12.97657 33.53125,-10.1875 9.91797,2.1289 18.11719,7.46484 25.00391,14.77343 7.28125,7.70313 12.21875,16.77735 15.17578,26.94141 0.13672,0.44922 0.24609,0.91406 0.32031,1.375 0.0156,0.20703 -0.0937,0.43359 -0.21875,1.00391 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path252" />
+ </g>
+ <g
+ clip-path="url(#9d28a89d3d)"
+ id="g258"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 46.824219,529.01953 v 29.27344 h 73.558591 v -29.27344 z m 28.085937,22.82422 c -0.01563,0 -0.01563,0 -0.01563,0 h -3.992187 c -0.0625,0 -0.125,-0.0469 -0.167969,-0.0937 L 67.273438,546.34766 63.78125,551.75 c -0.03125,0.0469 -0.09375,0.0937 -0.152344,0.0937 h -3.964844 c -0.07812,0 -0.136718,-0.0469 -0.167968,-0.10938 -0.03125,-0.0586 -0.03125,-0.13671 0.01563,-0.19531 l 5.519531,-8.41406 -5.003906,-7.71484 c -0.02734,-0.0586 -0.02734,-0.13672 0,-0.19532 0.03125,-0.0625 0.09375,-0.10937 0.167968,-0.10937 h 3.859376 c 0.0625,0 0.121093,0.0469 0.167968,0.0937 l 3.125,4.98828 3.050782,-4.98828 c 0.04687,-0.0469 0.105468,-0.0937 0.167968,-0.0937 h 3.828125 c 0.07422,0 0.136719,0.0469 0.167969,0.10937 0.02734,0.0586 0.02734,0.13672 0,0.19532 l -5.035156,7.83593 5.507812,8.25 c 0.02734,0.043 0.05859,0.0899 0.05859,0.15235 0,0.10156 -0.07422,0.19531 -0.183594,0.19531 z m 17.644532,-0.19922 c 0,0.10547 -0.09375,0.19922 -0.199219,0.19922 h -3.0625 c -0.109375,0 -0.183594,-0.0937 -0.183594,-0.19922 v -11.32031 l -2.882813,11.36719 c -0.01562,0.0898 -0.08984,0.15234 -0.183593,0.15234 h -3.1875 c -0.08984,0 -0.167969,-0.0625 -0.183594,-0.15234 l -2.851563,-11.36719 v 11.32031 c 0,0.10547 -0.08984,0.19531 -0.195312,0.19531 h -3.082031 c -0.105469,0 -0.183594,-0.0898 -0.183594,-0.19531 v -16.33984 c 0,-0.10547 0.07813,-0.19922 0.183594,-0.19922 H 81.5 c 0.08984,0 0.167969,0.0586 0.183594,0.15234 l 2.773437,10.45313 2.761719,-10.45313 c 0.01563,-0.0937 0.08984,-0.15234 0.183594,-0.15234 h 4.953125 c 0.105469,0 0.199219,0.0937 0.199219,0.19922 z m 14.882812,0 c 0,0.10547 -0.0742,0.19922 -0.18359,0.19922 H 95.726562 c -0.105468,0 -0.183593,-0.0937 -0.183593,-0.19922 v -16.20312 c 0,-0.10547 0.07813,-0.19922 0.183593,-0.19922 h 3.308594 c 0.105469,0 0.199219,0.0937 0.199219,0.19922 v 13.26953 h 8.019535 c 0.10937,0 0.18359,0.0742 0.18359,0.17968 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path256" />
+ </g>
+ <path
+ fill="#09102b"
+ d="m 10.753456,359.80895 h 58.707032 v 6.48437 H 10.753456 Z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path260" />
+ <path
+ fill="#09102b"
+ d="m 10.761268,287.53551 v 36.91406 h 58.70703 v -36.91406 z m 51.84766,32.34766 H 17.620643 c -0.835937,0 -1.523437,-0.6836 -1.523437,-1.51954 0,-0.85546 0.6875,-1.52343 1.523437,-1.52343 h 44.988285 c 0.82031,0 1.52343,0.66797 1.52343,1.52343 0,0.83594 -0.70312,1.51954 -1.52343,1.51954 z m 0,-10.65235 H 17.620643 c -0.835937,0 -1.523437,-0.68359 -1.523437,-1.51953 0,-0.85156 0.6875,-1.52344 1.523437,-1.52344 h 44.988285 c 0.82031,0 1.52343,0.67188 1.52343,1.52344 0,0.83594 -0.70312,1.51953 -1.52343,1.51953 z m 0,-10.64844 H 17.620643 c -0.835937,0 -1.523437,-0.6875 -1.523437,-1.52343 0,-0.85157 0.6875,-1.52344 1.523437,-1.52344 h 44.988285 c 0.82031,0 1.52343,0.67187 1.52343,1.52344 0,0.83593 -0.70312,1.52343 -1.52343,1.52343 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path262" />
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g270"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(126.27432,523.15898)"
+ id="g268">
+ <g
+ id="g266">
+ <path
+ d="m 4.6875,-23.234375 4.984375,9.15625 5.046875,-9.15625 H 18.6875 L 11.8125,-11.4375 18.6875,0 H 14.484375 L 9.5,-8.75 4.40625,0 H 0.4375 l 6.921875,-11.234375 -6.921875,-12 z m 0,0"
+ id="path264" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g278"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(144.65551,523.15898)"
+ id="g276">
+ <g
+ id="g274">
+ <path
+ d="m 2.6875,0 v -23.234375 h 6.546875 l 5.1875,18.140625 5.1875,-18.140625 H 26.1875 V 0 H 22.390625 V -19.0625 H 21.875 l -5.484375,18.109375 h -3.9375 l -5.5,-18.109375 H 6.4375 V 0 Z m 0,0"
+ id="path272" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g286"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(172.73611,523.15898)"
+ id="g284">
+ <g
+ id="g282">
+ <path
+ d="M 15.703125,0 H 2.6875 v -23.234375 h 3.75 v 19.875 h 9.265625 z m 0,0"
+ id="path280" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g294"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(126.27432,557.65898)"
+ id="g292">
+ <g
+ id="g290">
+ <path
+ d="m 0.4375,-19.875 v -3.359375 H 17.40625 V -19.875 H 10.859375 V 0 H 7.0625 v -19.875 z m 0,0"
+ id="path288" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g302"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(143.36677,557.65898)"
+ id="g300">
+ <g
+ id="g298">
+ <path
+ d="M 0.671875,-16.96875 H 4.3125 l 3.59375,13.8125 H 8.8125 l 3.609375,-13.8125 h 3.65625 L 9.640625,7.296875 H 6 L 8.046875,0 H 5.125 Z m 0,0"
+ id="path296" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g310"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(159.30615,557.65898)"
+ id="g308">
+ <g
+ id="g306">
+ <path
+ d="M 2.234375,7.296875 V -16.96875 H 5.90625 v 1.0625 c 1.5625,-0.945312 3.019531,-1.421875 4.375,-1.421875 2.238281,0 3.875,0.683594 4.90625,2.046875 1.039062,1.367188 1.5625,3.664062 1.5625,6.890625 0,3.21875 -0.59375,5.484375 -1.78125,6.796875 -1.179688,1.3125 -3.117188,1.96875 -5.8125,1.96875 -0.929688,0 -2,-0.105469 -3.21875,-0.3125 v 7.234375 z m 7.40625,-21.34375 c -1.0625,0 -2.132813,0.242187 -3.203125,0.71875 l -0.5,0.234375 v 10 c 0.90625,0.1875 1.898438,0.28125 2.984375,0.28125 1.539063,0 2.601563,-0.441406 3.1875,-1.328125 0.582031,-0.882813 0.875,-2.390625 0.875,-4.515625 0,-3.59375 -1.117187,-5.390625 -3.34375,-5.390625 z m 0,0"
+ id="path304" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g318"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(176.77166,557.65898)"
+ id="g316">
+ <g
+ id="g314">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path312" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g326"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(193.25366,557.65898)"
+ id="g324">
+ <g
+ id="g322">
+ <path
+ d="m 14.015625,-13.46875 c -2.679687,-0.363281 -4.617187,-0.546875 -5.8125,-0.546875 -1.199219,0 -2.03125,0.148437 -2.5,0.4375 -0.460937,0.28125 -0.6875,0.730469 -0.6875,1.34375 0,0.605469 0.253906,1.03125 0.765625,1.28125 0.507812,0.25 1.707031,0.542969 3.59375,0.875 1.894531,0.324219 3.238281,0.835937 4.03125,1.53125 0.789062,0.699219 1.1875,1.945313 1.1875,3.734375 0,1.78125 -0.574219,3.09375 -1.71875,3.9375 -1.148438,0.8359375 -2.8125,1.25 -5,1.25 -1.386719,0 -3.132812,-0.195312 -5.234375,-0.578125 L 1.59375,-0.375 1.734375,-3.453125 c 2.707031,0.355469 4.660156,0.53125 5.859375,0.53125 1.195312,0 2.050781,-0.144531 2.5625,-0.4375 0.507812,-0.289063 0.765625,-0.773437 0.765625,-1.453125 0,-0.675781 -0.246094,-1.144531 -0.734375,-1.40625 C 9.707031,-6.476562 8.546875,-6.757812 6.703125,-7.0625 4.859375,-7.375 3.503906,-7.859375 2.640625,-8.515625 c -0.855469,-0.65625 -1.28125,-1.851563 -1.28125,-3.59375 0,-1.738281 0.59375,-3.035156 1.78125,-3.890625 1.1875,-0.863281 2.707031,-1.296875 4.5625,-1.296875 1.445313,0 3.222656,0.183594 5.328125,0.546875 l 1.046875,0.203125 z m 0,0"
+ id="path320" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g334"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(208.41301,557.65898)"
+ id="g332">
+ <g
+ id="g330">
+ <path
+ d="M 0.671875,-16.96875 H 4.3125 l 3.59375,13.8125 H 8.8125 l 3.609375,-13.8125 h 3.65625 L 9.640625,7.296875 H 6 L 8.046875,0 H 5.125 Z m 0,0"
+ id="path328" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g342"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(224.35239,557.65898)"
+ id="g340">
+ <g
+ id="g338">
+ <path
+ d="m 14.015625,-13.46875 c -2.679687,-0.363281 -4.617187,-0.546875 -5.8125,-0.546875 -1.199219,0 -2.03125,0.148437 -2.5,0.4375 -0.460937,0.28125 -0.6875,0.730469 -0.6875,1.34375 0,0.605469 0.253906,1.03125 0.765625,1.28125 0.507812,0.25 1.707031,0.542969 3.59375,0.875 1.894531,0.324219 3.238281,0.835937 4.03125,1.53125 0.789062,0.699219 1.1875,1.945313 1.1875,3.734375 0,1.78125 -0.574219,3.09375 -1.71875,3.9375 -1.148438,0.8359375 -2.8125,1.25 -5,1.25 -1.386719,0 -3.132812,-0.195312 -5.234375,-0.578125 L 1.59375,-0.375 1.734375,-3.453125 c 2.707031,0.355469 4.660156,0.53125 5.859375,0.53125 1.195312,0 2.050781,-0.144531 2.5625,-0.4375 0.507812,-0.289063 0.765625,-0.773437 0.765625,-1.453125 0,-0.675781 -0.246094,-1.144531 -0.734375,-1.40625 C 9.707031,-6.476562 8.546875,-6.757812 6.703125,-7.0625 4.859375,-7.375 3.503906,-7.859375 2.640625,-8.515625 c -0.855469,-0.65625 -1.28125,-1.851563 -1.28125,-3.59375 0,-1.738281 0.59375,-3.035156 1.78125,-3.890625 1.1875,-0.863281 2.707031,-1.296875 4.5625,-1.296875 1.445313,0 3.222656,0.183594 5.328125,0.546875 l 1.046875,0.203125 z m 0,0"
+ id="path336" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g350"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(239.51175,557.65898)"
+ id="g348">
+ <g
+ id="g346">
+ <path
+ d="M 11.359375,-13.8125 H 6.6875 v 7.46875 c 0,1.375 0.097656,2.292969 0.296875,2.75 0.207031,0.449219 0.726563,0.671875 1.5625,0.671875 l 2.78125,-0.09375 L 11.5,-0.0625 C 9.988281,0.226562 8.835938,0.375 8.046875,0.375 c -1.929687,0 -3.25,-0.4375 -3.96875,-1.3125 -0.710937,-0.882812 -1.0625,-2.550781 -1.0625,-5 v -7.875 H 0.84375 v -3.15625 H 3.015625 V -21.875 H 6.6875 v 4.90625 h 4.671875 z m 0,0"
+ id="path344" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g358"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(250.90664,557.65898)"
+ id="g356">
+ <g
+ id="g354">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path352" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g366"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(267.38864,557.65898)"
+ id="g364">
+ <g
+ id="g362">
+ <path
+ d="M 5.9375,0 H 2.234375 V -16.96875 H 5.90625 v 1.0625 c 1.601562,-0.945312 3.070312,-1.421875 4.40625,-1.421875 1.96875,0 3.40625,0.554687 4.3125,1.65625 2.050781,-1.101563 4.09375,-1.65625 6.125,-1.65625 2.039062,0 3.476562,0.632813 4.3125,1.890625 0.84375,1.25 1.265625,3.367188 1.265625,6.34375 V 0 H 22.65625 v -8.984375 c 0,-1.832031 -0.1875,-3.132813 -0.5625,-3.90625 -0.367188,-0.769531 -1.136719,-1.15625 -2.3125,-1.15625 -1.023438,0 -2.121094,0.230469 -3.296875,0.6875 L 15.90625,-13.125 c 0.1875,0.449219 0.28125,1.898438 0.28125,4.34375 V 0 h -3.671875 v -8.71875 c 0,-2.007812 -0.183594,-3.398438 -0.546875,-4.171875 -0.355469,-0.769531 -1.148438,-1.15625 -2.375,-1.15625 -1.125,0 -2.179688,0.230469 -3.15625,0.6875 l -0.5,0.203125 z m 0,0"
+ id="path360" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g374"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(295.06227,557.65898)"
+ id="g372">
+ <g
+ id="g370">
+ <path
+ d="m 14.015625,-13.46875 c -2.679687,-0.363281 -4.617187,-0.546875 -5.8125,-0.546875 -1.199219,0 -2.03125,0.148437 -2.5,0.4375 -0.460937,0.28125 -0.6875,0.730469 -0.6875,1.34375 0,0.605469 0.253906,1.03125 0.765625,1.28125 0.507812,0.25 1.707031,0.542969 3.59375,0.875 1.894531,0.324219 3.238281,0.835937 4.03125,1.53125 0.789062,0.699219 1.1875,1.945313 1.1875,3.734375 0,1.78125 -0.574219,3.09375 -1.71875,3.9375 -1.148438,0.8359375 -2.8125,1.25 -5,1.25 -1.386719,0 -3.132812,-0.195312 -5.234375,-0.578125 L 1.59375,-0.375 1.734375,-3.453125 c 2.707031,0.355469 4.660156,0.53125 5.859375,0.53125 1.195312,0 2.050781,-0.144531 2.5625,-0.4375 0.507812,-0.289063 0.765625,-0.773437 0.765625,-1.453125 0,-0.675781 -0.246094,-1.144531 -0.734375,-1.40625 C 9.707031,-6.476562 8.546875,-6.757812 6.703125,-7.0625 4.859375,-7.375 3.503906,-7.859375 2.640625,-8.515625 c -0.855469,-0.65625 -1.28125,-1.851563 -1.28125,-3.59375 0,-1.738281 0.59375,-3.035156 1.78125,-3.890625 1.1875,-0.863281 2.707031,-1.296875 4.5625,-1.296875 1.445313,0 3.222656,0.183594 5.328125,0.546875 l 1.046875,0.203125 z m 0,0"
+ id="path368" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#0baef73a1e)"
+ id="g378"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 230.94531,263.10547 h -1.21875 V 254.125 c 0,-0.36719 -0.0703,-0.72266 -0.21094,-1.0625 -0.13671,-0.33594 -0.33593,-0.63672 -0.59765,-0.89844 -0.25781,-0.25781 -0.55469,-0.45703 -0.89063,-0.59765 -0.33984,-0.14063 -0.6875,-0.21094 -1.05468,-0.21094 h -2.44922 v -10.71094 c 0.004,-0.31641 -0.10547,-0.58594 -0.32032,-0.8125 L 209.78516,225.0625 c -0.23047,-0.26172 -0.51954,-0.39453 -0.86329,-0.39844 h -35.35546 c -0.14844,0 -0.29688,0.0312 -0.4375,0.0898 -0.14063,0.0586 -0.26563,0.14062 -0.3711,0.25 -0.10937,0.10546 -0.1914,0.23046 -0.25,0.375 -0.0586,0.14062 -0.0859,0.28515 -0.0859,0.4414 v 25.55078 h -2.48828 c -0.36328,0 -0.71484,0.0703 -1.05468,0.21094 -0.33594,0.14063 -0.63282,0.34375 -0.89063,0.60156 -0.25781,0.26172 -0.45703,0.5586 -0.59766,0.89844 -0.14062,0.33984 -0.21093,0.69141 -0.21093,1.05859 v 12.70313 h -0.44141 c -0.36328,0 -0.71484,0.0703 -1.05078,0.21094 -0.33984,0.14062 -0.63672,0.34375 -0.89453,0.60156 -0.25781,0.26172 -0.45703,0.55859 -0.59766,0.89844 -0.13672,0.33984 -0.20703,0.6914 -0.20703,1.05859 0,0 0,0.10156 0,0.16016 l 3.17578,23.74218 c 0.0117,0.35938 0.0898,0.70313 0.23438,1.03125 0.14843,0.32422 0.34765,0.61329 0.60547,0.86329 0.25781,0.25 0.55078,0.4414 0.88281,0.57421 0.32812,0.13282 0.67187,0.19922 1.02734,0.19922 h 57.07813 c 0.35547,0 0.69922,-0.0664 1.02734,-0.19922 0.33203,-0.13281 0.625,-0.32421 0.87891,-0.57031 0.25781,-0.25 0.46093,-0.53515 0.60547,-0.86328 0.14453,-0.32422 0.22656,-0.66797 0.24218,-1.02344 l 3.95313,-27.5039 c 0.004,-0.0547 0.004,-0.10938 0,-0.16407 0,-0.36718 -0.0742,-0.71875 -0.21485,-1.05468 -0.14062,-0.33985 -0.33984,-0.63672 -0.59765,-0.89453 -0.25781,-0.25782 -0.55469,-0.45704 -0.89063,-0.59375 -0.33593,-0.14063 -0.6875,-0.21094 -1.05078,-0.21094 z m -61.48828,3.73828 V 254.125 c 0.004,-0.12109 0.0469,-0.22656 0.13281,-0.3125 0.082,-0.0859 0.1875,-0.12891 0.3086,-0.13281 h 2.48437 v 13.16406 z m 33.60938,-3.19141 -1.95704,3.19141 h -26.39453 v -39.87109 h 33.08594 v 13.67187 c 0.0117,0.30859 0.12109,0.56641 0.33984,0.78516 0.21485,0.21484 0.47657,0.32422 0.78125,0.33203 h 13.28907 v 21.34375 h -18.12891 c -0.42578,0 -0.75391,0.17969 -0.98047,0.54687 z m 21.45703,-0.54687 v -9.42578 h 2.48437 c 0.1211,0.004 0.22656,0.0469 0.3125,0.13281 0.082,0.0859 0.12891,0.19141 0.12891,0.3125 v 8.98047 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path376" />
+ </g>
+ <path
+ fill="#09102b"
+ d="m 138.5308,35.426124 h 17.95313 c 0.15234,0 0.29687,-0.0312 0.4375,-0.0898 0.14062,-0.0586 0.26562,-0.14062 0.375,-0.25 0.10546,-0.10547 0.1875,-0.23047 0.24609,-0.37109 0.0586,-0.14453 0.0898,-0.28907 0.0898,-0.44532 0,-0.15234 -0.0312,-0.29687 -0.0898,-0.4414 -0.0586,-0.14063 -0.14063,-0.26563 -0.24609,-0.3711 -0.10938,-0.10937 -0.23438,-0.1914 -0.375,-0.25 -0.14063,-0.0586 -0.28516,-0.0898 -0.4375,-0.0898 H 138.5308 c -0.15234,0 -0.29687,0.0312 -0.4375,0.0898 -0.14062,0.0586 -0.26562,0.14063 -0.37109,0.25 -0.10938,0.10547 -0.19141,0.23047 -0.25,0.3711 -0.0586,0.14453 -0.0859,0.28906 -0.0859,0.4414 0,0.15625 0.0273,0.30079 0.0859,0.44532 0.0586,0.14062 0.14062,0.26562 0.25,0.37109 0.10547,0.10938 0.23047,0.19141 0.37109,0.25 0.14063,0.0586 0.28516,0.0898 0.4375,0.0898 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path380" />
+ <path
+ fill="#09102b"
+ d="m 144.88236,56.051124 h -6.35156 c -0.15234,0 -0.29687,0.0274 -0.4375,0.0859 -0.14062,0.0586 -0.26562,0.14063 -0.37109,0.25 -0.10938,0.10938 -0.19141,0.23438 -0.25,0.375 -0.0586,0.14063 -0.0859,0.28906 -0.0859,0.44141 0,0.15234 0.0273,0.30078 0.0859,0.4414 0.0586,0.14063 0.14062,0.26563 0.25,0.375 0.10547,0.10938 0.23047,0.19141 0.37109,0.25 0.14063,0.0586 0.28516,0.0859 0.4375,0.0859 h 6.35156 c 0.15235,0 0.30078,-0.0273 0.44141,-0.0859 0.14062,-0.0586 0.26172,-0.14062 0.37109,-0.25 0.10547,-0.10937 0.19141,-0.23437 0.25,-0.375 0.0547,-0.14062 0.0859,-0.28906 0.0859,-0.4414 0,-0.15235 -0.0312,-0.30078 -0.0859,-0.44141 -0.0586,-0.14062 -0.14453,-0.26562 -0.25,-0.375 -0.10937,-0.10937 -0.23047,-0.1914 -0.37109,-0.25 -0.14063,-0.0586 -0.28906,-0.0859 -0.44141,-0.0859 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path382" />
+ <path
+ fill="#09102b"
+ d="m 158.89799,56.051124 h -8.54688 c -0.14843,0 -0.29687,0.0274 -0.4375,0.0859 -0.14062,0.0586 -0.26562,0.14063 -0.37109,0.25 -0.10938,0.10938 -0.19141,0.23438 -0.25,0.375 -0.0586,0.14063 -0.0859,0.28906 -0.0859,0.44141 0,0.15234 0.0273,0.30078 0.0859,0.4414 0.0586,0.14063 0.14062,0.26563 0.25,0.375 0.10547,0.10938 0.23047,0.19141 0.37109,0.25 0.14063,0.0586 0.28907,0.0859 0.4375,0.0859 h 8.54688 c 0.15234,0 0.29687,-0.0273 0.4375,-0.0859 0.14062,-0.0586 0.26562,-0.14062 0.375,-0.25 0.10547,-0.10937 0.1875,-0.23437 0.24609,-0.375 0.0586,-0.14062 0.0898,-0.28906 0.0898,-0.4414 0,-0.15235 -0.0312,-0.30078 -0.0898,-0.44141 -0.0586,-0.14062 -0.14062,-0.26562 -0.24609,-0.375 -0.10938,-0.10937 -0.23438,-0.1914 -0.375,-0.25 -0.14063,-0.0586 -0.28516,-0.0859 -0.4375,-0.0859 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path384" />
+ <path
+ fill="#09102b"
+ d="m 138.5308,40.613624 h 20.30078 c 0.15235,0 0.30078,-0.0273 0.44141,-0.0859 0.14062,-0.0586 0.26562,-0.14453 0.37109,-0.25 0.10938,-0.10938 0.19141,-0.23438 0.25,-0.375 0.0586,-0.14063 0.0859,-0.28907 0.0859,-0.44141 0,-0.15625 -0.0273,-0.30078 -0.0859,-0.44141 -0.0586,-0.14453 -0.14062,-0.26953 -0.25,-0.375 -0.10547,-0.10937 -0.23047,-0.1914 -0.37109,-0.25 -0.14063,-0.0586 -0.28906,-0.0898 -0.44141,-0.0898 H 138.5308 c -0.15234,0 -0.29687,0.0312 -0.4375,0.0898 -0.14062,0.0586 -0.26562,0.14063 -0.37109,0.25 -0.10938,0.10547 -0.19141,0.23047 -0.25,0.375 -0.0586,0.14063 -0.0859,0.28516 -0.0859,0.44141 0,0.15234 0.0273,0.30078 0.0859,0.44141 0.0586,0.14062 0.14062,0.26562 0.25,0.375 0.10547,0.10547 0.23047,0.1914 0.37109,0.25 0.14063,0.0586 0.28516,0.0859 0.4375,0.0859 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path386" />
+ <path
+ fill="#09102b"
+ d="M 166.35111,50.269874 H 138.5308 c -0.15234,0 -0.29687,0.0312 -0.4375,0.0898 -0.14062,0.0586 -0.26562,0.14062 -0.37109,0.25 -0.10938,0.10547 -0.19141,0.23047 -0.25,0.375 -0.0586,0.14062 -0.0859,0.28515 -0.0859,0.4414 0,0.15235 0.0273,0.29688 0.0859,0.44141 0.0586,0.14063 0.14062,0.26563 0.25,0.37109 0.10547,0.10938 0.23047,0.19532 0.37109,0.25391 0.14063,0.0586 0.28516,0.0859 0.4375,0.0859 h 27.82031 c 0.15235,0 0.29688,-0.0273 0.4375,-0.0859 0.14063,-0.0586 0.26563,-0.14453 0.3711,-0.25391 0.10937,-0.10546 0.1914,-0.23046 0.25,-0.37109 0.0586,-0.14453 0.0859,-0.28906 0.0859,-0.44141 0,-0.15625 -0.0273,-0.30078 -0.0859,-0.4414 -0.0586,-0.14453 -0.14063,-0.26953 -0.25,-0.375 -0.10547,-0.10938 -0.23047,-0.19141 -0.3711,-0.25 -0.14062,-0.0586 -0.28515,-0.0898 -0.4375,-0.0898 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path388" />
+ <path
+ fill="#09102b"
+ d="m 172.45268,44.351914 h -33.95704 c -0.15234,0 -0.30078,0.0312 -0.4414,0.0898 -0.14063,0.0586 -0.26172,0.14062 -0.3711,0.25 -0.10937,0.10547 -0.1914,0.23047 -0.25,0.375 -0.0586,0.14062 -0.0859,0.28516 -0.0859,0.44141 0,0.15234 0.0273,0.30078 0.0859,0.4414 0.0586,0.14063 0.14063,0.26563 0.25,0.375 0.10938,0.10547 0.23047,0.19141 0.3711,0.25 0.14062,0.0586 0.28906,0.0859 0.4414,0.0859 h 33.95704 c 0.15234,0 0.29687,-0.0273 0.4375,-0.0859 0.14062,-0.0586 0.26562,-0.14453 0.375,-0.25 0.10546,-0.10937 0.1875,-0.23437 0.24609,-0.375 0.0586,-0.14062 0.0898,-0.28906 0.0898,-0.4414 0,-0.15625 -0.0312,-0.30079 -0.0898,-0.44141 -0.0586,-0.14453 -0.14063,-0.26953 -0.24609,-0.375 -0.10938,-0.10938 -0.23438,-0.19141 -0.375,-0.25 -0.14063,-0.0586 -0.28516,-0.0898 -0.4375,-0.0898 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path390" />
+ <g
+ clip-path="url(#1f4a27800a)"
+ id="g398"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ mask="url(#e94e818b4b)"
+ id="g396">
+ <g
+ transform="matrix(0.196004,0,0,0.194118,62.344152,227.08093)"
+ id="g394">
+ <image
+ x="0"
+ y="0"
+ width="463"
+ xlink:href="data:image/png;base64,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"
+ height="340"
+ preserveAspectRatio="xMidYMid"
+ id="image392" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g406"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(62.344152,330.62669)"
+ id="g404">
+ <g
+ id="g402">
+ <path
+ d="M 11.78125,0.390625 C 8.039062,0.390625 5.4375,-0.613281 3.96875,-2.625 2.5,-4.632812 1.765625,-7.8125 1.765625,-12.15625 1.765625,-16.5 2.507812,-19.722656 4,-21.828125 5.5,-23.941406 8.09375,-25 11.78125,-25 c 3.6875,0 6.269531,1.046875 7.75,3.140625 1.488281,2.09375 2.234375,5.324219 2.234375,9.6875 0,2.875 -0.308594,5.199219 -0.921875,6.96875 -0.605469,1.773437 -1.601562,3.121094 -2.984375,4.046875 l 3.015625,4.859375 -3.703125,1.71875 -3.203125,-5.25 c -0.449219,0.144531 -1.179688,0.21875 -2.1875,0.21875 z M 7.109375,-5.1875 c 0.8125,1.398438 2.367187,2.09375 4.671875,2.09375 2.300781,0 3.851562,-0.6875 4.65625,-2.0625 0.800781,-1.375 1.203125,-3.703125 1.203125,-6.984375 0,-3.28125 -0.417969,-5.660156 -1.25,-7.140625 -0.824219,-1.488281 -2.359375,-2.234375 -4.609375,-2.234375 -2.25,0 -3.796875,0.746094 -4.640625,2.234375 -0.835937,1.480469 -1.25,3.851562 -1.25,7.109375 0,3.25 0.40625,5.578125 1.21875,6.984375 z m 0,0"
+ id="path400" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g414"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(85.1083,330.62669)"
+ id="g412">
+ <g
+ id="g410">
+ <path
+ d="M 12.03125,-14.625 H 7.078125 v 7.90625 c 0,1.460938 0.101563,2.429688 0.3125,2.90625 0.21875,0.480469 0.769531,0.71875 1.65625,0.71875 L 12,-3.203125 l 0.171875,3.125 c -1.605469,0.3125 -2.824219,0.46875 -3.65625,0.46875 -2.042969,0 -3.4375,-0.4609375 -4.1875,-1.390625 -0.75,-0.9375 -1.125,-2.695312 -1.125,-5.28125 V -14.625 h -2.3125 v -3.328125 h 2.3125 v -5.21875 h 3.875 v 5.21875 h 4.953125 z m 0,0"
+ id="path408" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g420"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(97.172393,330.62669)"
+ id="g418">
+ <g
+ id="g416" />
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g428"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(104.28144,330.62669)"
+ id="g426">
+ <g
+ id="g424">
+ <path
+ d="m 17.453125,0 v -10.640625 h -10.625 V 0 H 2.84375 V -24.609375 H 6.828125 V -14.125 h 10.625 v -10.484375 h 4.03125 V 0 Z m 0,0"
+ id="path422" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g436"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(127.7637,330.62669)"
+ id="g434">
+ <g
+ id="g432">
+ <path
+ d="m 15.15625,-3.234375 1.015625,-0.109375 0.0625,2.90625 c -2.730469,0.550781 -5.148437,0.828125 -7.25,0.828125 -2.65625,0 -4.570313,-0.726563 -5.734375,-2.1875 -1.15625,-1.457031 -1.734375,-3.789063 -1.734375,-7 0,-6.375 2.59375,-9.5625 7.78125,-9.5625 5.03125,0 7.546875,2.746094 7.546875,8.234375 l -0.25,2.796875 H 5.453125 c 0.03125,1.492187 0.351563,2.585937 0.96875,3.28125 0.625,0.6875 1.785156,1.03125 3.484375,1.03125 1.707031,0 3.457031,-0.070313 5.25,-0.21875 z M 13,-10.34375 c 0,-1.769531 -0.28125,-3.007812 -0.84375,-3.71875 -0.5625,-0.707031 -1.515625,-1.0625 -2.859375,-1.0625 -1.335937,0 -2.308594,0.375 -2.921875,1.125 -0.617188,0.742188 -0.933594,1.960938 -0.953125,3.65625 z m 0,0"
+ id="path430" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g444"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(145.21372,330.62669)"
+ id="g442">
+ <g
+ id="g440">
+ <path
+ d="m 15.65625,-12.421875 v 8.1875 c 0.03125,0.523437 0.171875,0.914063 0.421875,1.171875 0.25,0.25 0.640625,0.40625 1.171875,0.46875 l -0.109375,2.984375 c -2.0625,0 -3.65625,-0.4414062 -4.78125,-1.328125 -1.917969,0.8867188 -3.84375,1.328125 -5.78125,1.328125 -3.574219,0 -5.359375,-1.898437 -5.359375,-5.703125 0,-1.820312 0.484375,-3.140625 1.453125,-3.953125 0.96875,-0.8125 2.460937,-1.300781 4.484375,-1.46875 l 4.625,-0.40625 v -1.28125 c 0,-0.957031 -0.210938,-1.628906 -0.625,-2.015625 -0.417969,-0.382812 -1.039062,-0.578125 -1.859375,-0.578125 -1.53125,0 -3.445313,0.09375 -5.734375,0.28125 l -1.15625,0.07813 -0.140625,-2.765625 c 2.601563,-0.625 5,-0.9375 7.1875,-0.9375 2.195313,0 3.78125,0.476563 4.75,1.421875 0.96875,0.949219 1.453125,2.453125 1.453125,4.515625 z M 7.609375,-7.96875 c -1.648437,0.136719 -2.46875,1.03125 -2.46875,2.6875 0,1.65625 0.726563,2.484375 2.1875,2.484375 1.195313,0 2.46875,-0.191406 3.8125,-0.578125 L 11.78125,-3.59375 V -8.375 Z m 0,0"
+ id="path438" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g452"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(162.62784,330.62669)"
+ id="g450">
+ <g
+ id="g448">
+ <path
+ d="M 17.03125,-25.4375 V 0 h -3.890625 v -0.9375 c -1.742187,0.8867188 -3.34375,1.328125 -4.8125,1.328125 -2.34375,0 -4.0625,-0.703125 -5.15625,-2.109375 -1.085937,-1.414062 -1.625,-3.785156 -1.625,-7.109375 0,-3.332031 0.601563,-5.753906 1.8125,-7.265625 1.207031,-1.507812 3.09375,-2.265625 5.65625,-2.265625 0.863281,0 2.226563,0.15625 4.09375,0.46875 V -25.4375 Z M 12.5,-3.734375 l 0.609375,-0.25 V -14.625 c -1.4375,-0.238281 -2.765625,-0.359375 -3.984375,-0.359375 -2.417969,0 -3.625,2.015625 -3.625,6.046875 0,2.199219 0.28125,3.726562 0.84375,4.578125 0.5625,0.84375 1.453125,1.265625 2.671875,1.265625 1.21875,0 2.378906,-0.210938 3.484375,-0.640625 z m 0,0"
+ id="path446" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g460"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(181.22687,330.62669)"
+ id="g458">
+ <g
+ id="g456">
+ <path
+ d="m 15.15625,-3.234375 1.015625,-0.109375 0.0625,2.90625 c -2.730469,0.550781 -5.148437,0.828125 -7.25,0.828125 -2.65625,0 -4.570313,-0.726563 -5.734375,-2.1875 -1.15625,-1.457031 -1.734375,-3.789063 -1.734375,-7 0,-6.375 2.59375,-9.5625 7.78125,-9.5625 5.03125,0 7.546875,2.746094 7.546875,8.234375 l -0.25,2.796875 H 5.453125 c 0.03125,1.492187 0.351563,2.585937 0.96875,3.28125 0.625,0.6875 1.785156,1.03125 3.484375,1.03125 1.707031,0 3.457031,-0.070313 5.25,-0.21875 z M 13,-10.34375 c 0,-1.769531 -0.28125,-3.007812 -0.84375,-3.71875 -0.5625,-0.707031 -1.515625,-1.0625 -2.859375,-1.0625 -1.335937,0 -2.308594,0.375 -2.921875,1.125 -0.617188,0.742188 -0.933594,1.960938 -0.953125,3.65625 z m 0,0"
+ id="path454" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g468"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(198.6769,330.62669)"
+ id="g466">
+ <g
+ id="g464">
+ <path
+ d="M 2.375,0 V -17.953125 H 6.25 v 2.140625 c 2.03125,-1.3125 4.066406,-2.160156 6.109375,-2.546875 v 3.921875 c -2.0625,0.40625 -3.824219,0.933594 -5.28125,1.578125 L 6.28125,-12.53125 V 0 Z m 0,0"
+ id="path462" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g476"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(210.84872,330.62669)"
+ id="g474">
+ <g
+ id="g472">
+ <path
+ d="m 14.828125,-14.265625 c -2.824219,-0.375 -4.871094,-0.5625 -6.140625,-0.5625 -1.261719,0 -2.140625,0.152344 -2.640625,0.453125 -0.492187,0.292969 -0.734375,0.761719 -0.734375,1.40625 0,0.648438 0.269531,1.105469 0.8125,1.375 0.539062,0.261719 1.8125,0.5625 3.8125,0.90625 2,0.34375 3.414062,0.890625 4.25,1.640625 0.84375,0.742187 1.265625,2.058594 1.265625,3.953125 0,1.886719 -0.609375,3.273438 -1.828125,4.15625 -1.210938,0.8867188 -2.976562,1.328125 -5.296875,1.328125 -1.460937,0 -3.304687,-0.203125 -5.53125,-0.609375 L 1.6875,-0.390625 1.828125,-3.65625 c 2.875,0.375 4.945313,0.5625 6.21875,0.5625 1.269531,0 2.171875,-0.148438 2.703125,-0.453125 0.539062,-0.3125 0.8125,-0.828125 0.8125,-1.546875 0,-0.71875 -0.261719,-1.210938 -0.78125,-1.484375 -0.511719,-0.28125 -1.742188,-0.582031 -3.6875,-0.90625 -1.949219,-0.320313 -3.382812,-0.832031 -4.296875,-1.53125 -0.90625,-0.695313 -1.359375,-1.96875 -1.359375,-3.8125 0,-1.84375 0.625,-3.21875 1.875,-4.125 1.257812,-0.90625 2.875,-1.359375 4.84375,-1.359375 1.53125,0 3.410156,0.1875 5.640625,0.5625 l 1.109375,0.21875 z m 0,0"
+ id="path470" />
+ </g>
+ </g>
+ </g>
+ <g
+ mask="url(#8f2a27f6f4)"
+ id="g482"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="matrix(0.198482,0,0,0.198482,536.61425,471.98102)"
+ id="g480">
+ <image
+ x="0"
+ y="0"
+ width="461"
+ xlink:href="data:image/png;base64,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"
+ height="461"
+ preserveAspectRatio="xMidYMid"
+ id="image478" />
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g490"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(633.94891,514.05933)"
+ id="g488">
+ <g
+ id="g486">
+ <path
+ d="M 0.8125,-23.234375 H 4.78125 L 8.109375,-3.25 H 8.8125 l 4.421875,-19.921875 h 4.40625 L 22.046875,-3.25 h 0.75 L 26.125,-23.234375 h 3.96875 L 25.515625,0 H 19.4375 l -4,-18.625 L 11.46875,0 H 5.359375 Z m 0,0"
+ id="path484" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g498"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(664.09827,514.05933)"
+ id="g496">
+ <g
+ id="g494">
+ <path
+ d="M 5.9375,0 H 2.234375 V -24.015625 H 5.9375 v 7.9375 c 1.675781,-0.832031 3.222656,-1.25 4.640625,-1.25 2.257813,0 3.800781,0.640625 4.625,1.921875 0.832031,1.273438 1.25,3.375 1.25,6.3125 V 0 H 12.75 v -8.984375 c 0,-1.832031 -0.195312,-3.132813 -0.578125,-3.90625 -0.386719,-0.769531 -1.199219,-1.15625 -2.4375,-1.15625 -1.085937,0 -2.167969,0.183594 -3.25,0.546875 L 5.9375,-13.296875 Z m 0,0"
+ id="path492" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g506"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(681.869,514.05933)"
+ id="g504">
+ <g
+ id="g502">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path500" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g514"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(698.351,514.05933)"
+ id="g512">
+ <g
+ id="g510">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path508" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g522"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(714.833,514.05933)"
+ id="g520">
+ <g
+ id="g518">
+ <path
+ d="M 2.4375,0 V -24.015625 H 6.140625 V 0 Z m 0,0"
+ id="path516" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g530"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(633.94891,548.55933)"
+ id="g528">
+ <g
+ id="g526">
+ <path
+ d="m 11.1875,-7.21875 h -4.75 V 0 h -3.75 v -23.234375 h 8.5 c 5.269531,0 7.90625,2.601563 7.90625,7.796875 0,2.667969 -0.664062,4.703125 -1.984375,6.109375 -1.324219,1.40625 -3.296875,2.109375 -5.921875,2.109375 z m -4.75,-3.265625 h 4.71875 c 2.71875,0 4.078125,-1.648437 4.078125,-4.953125 0,-1.582031 -0.328125,-2.734375 -0.984375,-3.453125 -0.65625,-0.726563 -1.6875,-1.09375 -3.09375,-1.09375 H 6.4375 Z m 0,0"
+ id="path524" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g538"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(653.24578,548.55933)"
+ id="g536">
+ <g
+ id="g534">
+ <path
+ d="M 14.796875,-11.734375 V -4 c 0.01953,0.5 0.144531,0.871094 0.375,1.109375 0.238281,0.230469 0.609375,0.382813 1.109375,0.453125 L 16.1875,0.375 c -1.949219,0 -3.453125,-0.4140625 -4.515625,-1.25 -1.8125,0.8359375 -3.636719,1.25 -5.46875,1.25 -3.367187,0 -5.046875,-1.796875 -5.046875,-5.390625 0,-1.71875 0.457031,-2.960937 1.375,-3.734375 0.914062,-0.769531 2.320312,-1.234375 4.21875,-1.390625 l 4.375,-0.375 v -1.21875 c 0,-0.90625 -0.199219,-1.535156 -0.59375,-1.890625 -0.398438,-0.363281 -0.980469,-0.546875 -1.75,-0.546875 -1.449219,0 -3.257812,0.08984 -5.421875,0.265625 l -1.09375,0.0625 -0.125,-2.609375 c 2.457031,-0.582031 4.722656,-0.875 6.796875,-0.875 2.070312,0 3.566406,0.449219 4.484375,1.34375 0.914063,0.886719 1.375,2.304687 1.375,4.25 z M 7.1875,-7.53125 c -1.5625,0.136719 -2.34375,0.984375 -2.34375,2.546875 0,1.5625 0.691406,2.34375 2.078125,2.34375 1.125,0 2.320313,-0.179687 3.59375,-0.546875 L 11.125,-3.390625 V -7.90625 Z m 0,0"
+ id="path532" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g546"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(669.69387,548.55933)"
+ id="g544">
+ <g
+ id="g542">
+ <path
+ d="m 8.578125,-17.328125 c 1.195313,0 2.613281,0.15625 4.25,0.46875 l 0.84375,0.171875 -0.140625,2.921875 c -1.78125,-0.1875 -3.105469,-0.28125 -3.96875,-0.28125 -1.71875,0 -2.875,0.386719 -3.46875,1.15625 -0.585938,0.773437 -0.875,2.21875 -0.875,4.34375 0,2.125 0.28125,3.59375 0.84375,4.40625 0.570312,0.8125 1.75,1.21875 3.53125,1.21875 L 13.5625,-3.1875 13.671875,-0.234375 C 11.390625,0.171875 9.671875,0.375 8.515625,0.375 5.929688,0.375 4.113281,-0.316406 3.0625,-1.703125 2.019531,-3.097656 1.5,-5.378906 1.5,-8.546875 c 0,-3.164063 0.550781,-5.421875 1.65625,-6.765625 1.101562,-1.34375 2.910156,-2.015625 5.421875,-2.015625 z m 0,0"
+ id="path540" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g554"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(683.93754,548.55933)"
+ id="g552">
+ <g
+ id="g550">
+ <path
+ d="M 5.9375,0 H 2.234375 V -24.015625 H 5.9375 v 13.875 l 2.109375,-0.203125 4,-6.625 H 16.1875 L 11.296875,-9.015625 16.453125,0 H 12.28125 L 8.140625,-7.15625 5.9375,-6.921875 Z m 0,0"
+ id="path548" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g562"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(700.11432,548.55933)"
+ id="g560">
+ <g
+ id="g558">
+ <path
+ d="M 14.796875,-11.734375 V -4 c 0.01953,0.5 0.144531,0.871094 0.375,1.109375 0.238281,0.230469 0.609375,0.382813 1.109375,0.453125 L 16.1875,0.375 c -1.949219,0 -3.453125,-0.4140625 -4.515625,-1.25 -1.8125,0.8359375 -3.636719,1.25 -5.46875,1.25 -3.367187,0 -5.046875,-1.796875 -5.046875,-5.390625 0,-1.71875 0.457031,-2.960937 1.375,-3.734375 0.914062,-0.769531 2.320312,-1.234375 4.21875,-1.390625 l 4.375,-0.375 v -1.21875 c 0,-0.90625 -0.199219,-1.535156 -0.59375,-1.890625 -0.398438,-0.363281 -0.980469,-0.546875 -1.75,-0.546875 -1.449219,0 -3.257812,0.08984 -5.421875,0.265625 l -1.09375,0.0625 -0.125,-2.609375 c 2.457031,-0.582031 4.722656,-0.875 6.796875,-0.875 2.070312,0 3.566406,0.449219 4.484375,1.34375 0.914063,0.886719 1.375,2.304687 1.375,4.25 z M 7.1875,-7.53125 c -1.5625,0.136719 -2.34375,0.984375 -2.34375,2.546875 0,1.5625 0.691406,2.34375 2.078125,2.34375 1.125,0 2.320313,-0.179687 3.59375,-0.546875 L 11.125,-3.390625 V -7.90625 Z m 0,0"
+ id="path556" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g570"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(716.56241,548.55933)"
+ id="g568">
+ <g
+ id="g566">
+ <path
+ d="m 17.0625,2.3125 c 0,3.707031 -2.683594,5.5625 -8.046875,5.5625 C 6.441406,7.875 4.53125,7.519531 3.28125,6.8125 2.039062,6.113281 1.421875,4.835938 1.421875,2.984375 1.421875,2.148438 1.625,1.429688 2.03125,0.828125 2.4375,0.234375 3.09375,-0.414062 4,-1.125 3.257812,-1.613281 2.890625,-2.4375 2.890625,-3.59375 c 0,-0.457031 0.300781,-1.191406 0.90625,-2.203125 L 4.109375,-6.3125 C 2.472656,-7.28125 1.65625,-8.972656 1.65625,-11.390625 c 0,-2.039063 0.609375,-3.535156 1.828125,-4.484375 1.226563,-0.945312 2.882813,-1.421875 4.96875,-1.421875 0.988281,0 1.96875,0.109375 2.9375,0.328125 L 11.90625,-16.859375 17.171875,-17 v 2.984375 l -2.828125,-0.15625 c 0.613281,0.792969 0.921875,1.71875 0.921875,2.78125 0,2.210937 -0.5625,3.742187 -1.6875,4.59375 -1.117187,0.84375 -2.859375,1.265625 -5.234375,1.265625 -0.585938,0 -1.078125,-0.046875 -1.484375,-0.140625 C 6.535156,-4.898438 6.375,-4.300781 6.375,-3.875 c 0,0.417969 0.207031,0.703125 0.625,0.859375 0.414062,0.15625 1.429688,0.246094 3.046875,0.265625 2.6875,0.023438 4.523437,0.386719 5.515625,1.09375 1,0.699219 1.5,2.019531 1.5,3.96875 z M 5.046875,2.640625 c 0,0.789063 0.316406,1.351563 0.953125,1.6875 0.632812,0.34375 1.722656,0.515625 3.265625,0.515625 2.726563,0 4.09375,-0.777344 4.09375,-2.328125 0,-0.886719 -0.246094,-1.449219 -0.734375,-1.6875 C 12.144531,0.585938 11.179688,0.457031 9.734375,0.4375 L 6.40625,0.234375 C 5.914062,0.640625 5.566406,1.019531 5.359375,1.375 5.148438,1.726562 5.046875,2.148438 5.046875,2.640625 Z m 0.28125,-14.03125 c 0,1.03125 0.242187,1.792969 0.734375,2.28125 0.5,0.492187 1.300781,0.734375 2.40625,0.734375 1.113281,0 1.910156,-0.242188 2.390625,-0.734375 0.488281,-0.488281 0.734375,-1.25 0.734375,-2.28125 0,-1.039063 -0.25,-1.804687 -0.75,-2.296875 -0.492188,-0.488281 -1.289062,-0.734375 -2.390625,-0.734375 -2.085937,0 -3.125,1.011719 -3.125,3.03125 z m 0,0"
+ id="path564" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g578"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(733.62094,548.55933)"
+ id="g576">
+ <g
+ id="g574">
+ <path
+ d="m 14.3125,-3.046875 0.953125,-0.109375 0.0625,2.75 C 12.753906,0.113281 10.472656,0.375 8.484375,0.375 5.972656,0.375 4.164062,-0.3125 3.0625,-1.6875 1.96875,-3.070312 1.421875,-5.28125 1.421875,-8.3125 c 0,-6.007812 2.453125,-9.015625 7.359375,-9.015625 4.75,0 7.125,2.589844 7.125,7.765625 l -0.234375,2.640625 H 5.15625 c 0.019531,1.40625 0.320312,2.4375 0.90625,3.09375 0.59375,0.65625 1.691406,0.984375 3.296875,0.984375 1.601563,0 3.253906,-0.066406 4.953125,-0.203125 z m -2.03125,-6.71875 c 0,-1.675781 -0.265625,-2.847656 -0.796875,-3.515625 -0.53125,-0.664062 -1.433594,-1 -2.703125,-1 -1.261719,0 -2.183594,0.355469 -2.765625,1.0625 -0.574219,0.699219 -0.871094,1.851562 -0.890625,3.453125 z m 0,0"
+ id="path572" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#000000"
+ fill-opacity="1"
+ id="g586"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(750.10294,548.55933)"
+ id="g584">
+ <g
+ id="g582">
+ <path
+ d="m 14.015625,-13.46875 c -2.679687,-0.363281 -4.617187,-0.546875 -5.8125,-0.546875 -1.199219,0 -2.03125,0.148437 -2.5,0.4375 -0.460937,0.28125 -0.6875,0.730469 -0.6875,1.34375 0,0.605469 0.253906,1.03125 0.765625,1.28125 0.507812,0.25 1.707031,0.542969 3.59375,0.875 1.894531,0.324219 3.238281,0.835937 4.03125,1.53125 0.789062,0.699219 1.1875,1.945313 1.1875,3.734375 0,1.78125 -0.574219,3.09375 -1.71875,3.9375 -1.148438,0.8359375 -2.8125,1.25 -5,1.25 -1.386719,0 -3.132812,-0.195312 -5.234375,-0.578125 L 1.59375,-0.375 1.734375,-3.453125 c 2.707031,0.355469 4.660156,0.53125 5.859375,0.53125 1.195312,0 2.050781,-0.144531 2.5625,-0.4375 0.507812,-0.289063 0.765625,-0.773437 0.765625,-1.453125 0,-0.675781 -0.246094,-1.144531 -0.734375,-1.40625 C 9.707031,-6.476562 8.546875,-6.757812 6.703125,-7.0625 4.859375,-7.375 3.503906,-7.859375 2.640625,-8.515625 c -0.855469,-0.65625 -1.28125,-1.851563 -1.28125,-3.59375 0,-1.738281 0.59375,-3.035156 1.78125,-3.890625 1.1875,-0.863281 2.707031,-1.296875 4.5625,-1.296875 1.445313,0 3.222656,0.183594 5.328125,0.546875 l 1.046875,0.203125 z m 0,0"
+ id="path580" />
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#9cd47c7ee3)"
+ id="g596"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ clip-path="url(#69785d3302)"
+ id="g594">
+ <g
+ clip-path="url(#9c0953b9a2)"
+ id="g592">
+ <g
+ clip-path="url(#8e32f12866)"
+ id="g590">
+ <path
+ fill="#09102b"
+ d="m 358.17187,562.08984 c -1.19531,0.76172 -2.16015,1.45703 -3.19921,2.02344 -3.46094,1.87891 -6.86329,3.89453 -10.45313,5.5 -3.87109,1.73047 -8.14062,-0.26953 -10.125,-4.14453 -0.5,-0.96484 -1.69141,-1.5625 -2.67578,-2.41797 -0.13672,-1.35937 1.17969,-1.5625 2.09375,-2.03906 8.29297,-4.31641 15.45703,-10.17188 22.07812,-16.66406 2.53516,-2.48047 4.60938,-5.44922 6.80079,-8.26563 1.71875,-2.21484 1.94921,-2.53516 4.60546,-1.53125 4.74219,1.79297 8.49219,4.66797 10.34375,9.73828 3.22657,8.80469 6.95704,17.42969 8.59375,26.74219 0.26172,1.51172 0.33594,3.0625 0.59375,5.5 -3.77343,-1.86719 -7.05859,-2.78516 -8.24609,-6.56641 -0.72656,-2.32031 -1.48828,-4.61718 -2.5,-7.78906 -1.25781,2.66406 -2.09766,4.50781 -2.99219,6.32031 -6.76172,13.64844 -16.28906,24.96875 -29.98828,31.73828 -12.46484,6.16797 -25.84765,9.05469 -39.78906,5.21875 -11.70703,-3.23437 -20.39844,-10.70703 -27.02734,-20.60156 -2.64844,-3.96875 -4.57422,-8.4375 -6.70313,-12.73828 -0.55469,-1.11328 -0.65234,-2.44141 -0.95312,-3.68359 0.30078,-0.15625 0.60156,-0.31641 0.90625,-0.47657 1.17578,1.30469 2.42578,2.55469 3.48828,3.94532 0.66406,0.87109 1.05859,1.94922 1.53515,2.95312 6.10547,12.90625 16.76953,18.96094 30.5625,19.90625 10.53516,0.72656 20.27344,-2.26562 29.27735,-7.62109 9.51172,-5.64063 17.07812,-13.32813 22.98047,-22.6836 0.26953,-0.41406 0.51171,-0.84765 0.71875,-1.28906 0.0781,-0.20312 0.0351,-0.46484 0.0742,-1.07422 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path588" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#a3af3eb6b6)"
+ id="g600"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 704.36719,330.69531 c 1.40625,-2.07812 3.07422,-1.63672 4.66797,-1.07812 4.41406,1.53125 8.38281,3.79297 11.63281,7.23828 10.34375,10.98828 17.05859,23.99609 20.78125,38.50781 3.82031,14.875 2.98047,29.55469 -3.1211,43.75 -2.87109,6.67969 -6.11328,13.20703 -9.29687,20.03516 0.74219,-0.2461 1.6875,-0.47266 2.58203,-0.85938 6.08203,-2.59765 7.51172,-2.37109 12.3125,2.26953 1.07422,1.03516 1.95703,2.26563 3.19531,3.70703 -1.25,0.77735 -2.1289,1.35547 -3.04687,1.88672 -9.82422,5.69532 -19.75781,11.22266 -29.42188,17.19922 -2.34375,1.44531 -4.15234,1.31641 -6.14453,0.36719 -4.0039,-1.91797 -6.86328,-5.28906 -9.32812,-8.80078 -0.86328,-1.22656 -0.58203,-3.52344 -0.33594,-5.25781 1.86328,-12.69922 2.53906,-25.44922 1.51953,-38.23438 -0.32422,-3.98828 -1.25,-7.91797 -1.94922,-12.22656 1.26953,-0.47266 2.67969,0.3125 3.875,1.0664 5.60547,3.54297 10.27735,7.85157 11.26563,14.91797 0.46484,3.33985 0.95703,6.66797 1.39062,10.00782 0.19141,1.48437 0.23438,2.99218 0.375,4.83593 7.40625,-6.82031 14.4961,-36.78515 12.53906,-51.98437 -2.3789,-18.48047 -10.55859,-34.16406 -23.49218,-47.34766 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path598" />
+ </g>
+ <g
+ clip-path="url(#31f8f05393)"
+ id="g610"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ clip-path="url(#41889181af)"
+ id="g608">
+ <g
+ clip-path="url(#fe9d13e8b4)"
+ id="g606">
+ <g
+ clip-path="url(#6c6e35ef02)"
+ id="g604">
+ <path
+ fill="#09102b"
+ d="m 509.19922,356.76172 c -0.71094,1.38672 0.0273,2.15234 0.80469,2.83984 2.14062,1.92188 4.55078,3.38281 7.39453,4.10156 9.04687,2.27735 18.11718,1.99219 27.11328,-0.35156 9.22656,-2.40234 16.95703,-7.25781 22.86719,-14.80469 2.77734,-3.55078 5.36328,-7.2539 8.1289,-11.01953 0.0859,0.47657 0.2461,1.05469 0.30078,1.65235 0.39453,4.05468 0.94141,4.75781 4.89453,5.94922 0.88282,0.27343 1.8125,0.3789 2.96485,0.61328 0.0508,-0.90625 0.10547,-1.55469 0.11719,-2.20703 0.17968,-7.00391 0.23437,-14.01172 0.61328,-21.01172 0.0859,-1.69922 -0.52344,-2.63282 -1.62891,-3.42188 -2.23047,-1.58203 -4.91797,-2.11328 -7.55859,-2.39062 -0.92188,-0.0937 -2.08594,0.74609 -2.95703,1.39843 -6.35157,4.8125 -13.08594,9 -20.34375,12.28516 -2.26172,1.01953 -4.67579,1.70313 -7.22657,2.61719 0.1211,0.82422 0.96875,1.35156 1.73047,1.76562 3.59375,1.96094 7.32422,3.1836 11.46094,1.59766 1.95703,-0.75 3.91406,-1.48047 5.85547,-2.25 0.86719,-0.34375 1.69922,-0.77344 2.74219,-1.25 -1.50782,6.03516 -15.69532,18.84375 -24.54297,22.34766 -10.75782,4.26171 -21.71485,4.55859 -32.73047,1.53906 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path602" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ clip-path="url(#9d2f7452d2)"
+ id="g614"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 547.03516,293.51172 h 54.54296 c 1.38282,0 2.51563,-1.12891 2.51563,-2.50781 v -40.83594 h -59.57422 v 40.83594 c 0,1.3789 1.13281,2.50781 2.51563,2.50781 z m 16.36328,-33.44531 h 21.8125 c 1.5,0 2.72656,1.22265 2.72656,2.71484 0,1.49219 -1.22656,2.71484 -2.72656,2.71484 h -21.8125 c -1.4961,0 -2.72266,-1.22265 -2.72266,-2.71484 0,-1.49219 1.22656,-2.71484 2.72266,-2.71484 z m 0,0"
+ fill-opacity="1"
+ fill-rule="evenodd"
+ id="path612" />
+ </g>
+ <g
+ clip-path="url(#5d999a0038)"
+ id="g618"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 554.07812,219.76172 h 1.70313 c 1.91797,0 3.48047,1.55859 3.48047,3.47265 0,1.91016 -1.5625,3.46875 -3.48047,3.46875 h -8.76953 c -1.91797,0 -3.48047,-1.55859 -3.48047,-3.46875 0,-1.83984 1.44922,-3.35546 3.26562,-3.46484 v 1.73828 c -0.85546,0.10938 -1.52734,0.84375 -1.52734,1.72656 0,0.87891 0.67188,1.61719 1.52734,1.72266 v 0.004 h 0.0469 c 0.0547,0.008 0.10937,0.008 0.16797,0.008 h 8.76953 c 0.95703,0 1.74219,-0.78125 1.74219,-1.73438 0,-0.95703 -0.78516,-1.73828 -1.74219,-1.73828 h -1.70313 z m 0,0"
+ fill-opacity="1"
+ fill-rule="nonzero"
+ id="path616" />
+ </g>
+ <g
+ clip-path="url(#a4f0b4e13e)"
+ id="g622"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="M 594.1875,248.43359 H 548.53516 V 228.4375 h 7.24609 c 2.875,0 5.21875,-2.33594 5.21875,-5.20313 0,-2.86718 -2.34375,-5.20703 -5.21875,-5.20703 h -3.44141 v 5.20313 h -3.80468 v -6.04297 c 0,-0.92188 0.73437,-1.67578 1.6289,-1.67578 h 42.39453 c 0.89844,0 1.62891,0.7539 1.62891,1.67578 z m -39.69922,-5.64062 h 33.75 v 1.73047 h -33.75 z m 0,-4.61719 h 33.75 v 1.73438 h -33.75 z m 8.23047,-14.98047 h 17.28906 v 1.73438 h -17.28906 z m 4.13281,-3.77734 h 9.01953 v 1.73437 h -9.01953 z m -12.36328,14.14453 h 33.75 v 1.73437 h -33.75 z m 0,0"
+ fill-opacity="1"
+ fill-rule="evenodd"
+ id="path620" />
+ </g>
+ <g
+ clip-path="url(#0ea259bc34)"
+ id="g626"
+ transform="translate(-43.488732,-201.52699)">
+ <path
+ fill="#09102b"
+ d="m 595.92969,248.43359 h 4.14843 V 217.1875 c 0,-0.92188 -0.73437,-1.67578 -1.63281,-1.67578 h -2.95312 c 0.27734,0.49609 0.4375,1.07031 0.4375,1.67578 z m 0,0"
+ fill-opacity="1"
+ fill-rule="evenodd"
+ id="path624" />
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g634"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(549.69852,280.96421)"
+ id="g632">
+ <g
+ id="g630">
+ <path
+ d="m 4.421875,0.109375 c -0.75,0 -1.414063,-0.1484375 -1.984375,-0.453125 -0.5625,-0.3125 -1.007812,-0.773438 -1.328125,-1.390625 -0.3125,-0.625 -0.46875,-1.394531 -0.46875,-2.3125 0,-0.90625 0.15625,-1.671875 0.46875,-2.296875 0.320313,-0.625 0.765625,-1.085938 1.328125,-1.390625 0.570312,-0.3125 1.234375,-0.46875 1.984375,-0.46875 0.78125,0 1.441406,0.152344 1.984375,0.453125 0.539062,0.304688 0.925781,0.765625 1.15625,1.390625 l -1.15625,0.71875 H 6.265625 c -0.179687,-0.425781 -0.417969,-0.726563 -0.71875,-0.90625 -0.292969,-0.1875 -0.667969,-0.28125 -1.125,-0.28125 -0.679687,0 -1.203125,0.226563 -1.578125,0.671875 -0.375,0.4375 -0.5625,1.140625 -0.5625,2.109375 0,0.96875 0.1875,1.679687 0.5625,2.125 0.375,0.4375 0.898438,0.65625 1.578125,0.65625 1.050781,0 1.691406,-0.507813 1.921875,-1.53125 h 0.140625 l 1.1875,0.609375 C 7.441406,-1.414062 7.0625,-0.835938 6.53125,-0.453125 6,-0.078125 5.296875,0.109375 4.421875,0.109375 Z m 0,0"
+ id="path628" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g642"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(557.62495,280.96421)"
+ id="g640">
+ <g
+ id="g638">
+ <path
+ d="m 4.171875,-8.09375 c 0.582031,0 1.078125,0.109375 1.484375,0.328125 0.414062,0.210937 0.726562,0.507813 0.9375,0.890625 0.207031,0.375 0.3125,0.820312 0.3125,1.328125 0,0.5 -0.105469,0.945313 -0.3125,1.328125 -0.210938,0.375 -0.523438,0.671875 -0.9375,0.890625 -0.40625,0.210937 -0.902344,0.3125 -1.484375,0.3125 H 2.65625 V 0 H 1.046875 v -8.09375 z m -0.203125,3.8125 c 0.882812,0 1.328125,-0.421875 1.328125,-1.265625 0,-0.84375 -0.445313,-1.265625 -1.328125,-1.265625 h -1.3125 v 2.53125 z m 0,0"
+ id="path636" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g650"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(565.00968,280.96421)"
+ id="g648">
+ <g
+ id="g646">
+ <path
+ d="M 1.34375,2.59375 C 1.082031,2.59375 0.847656,2.570312 0.640625,2.53125 0.429688,2.488281 0.257812,2.4375 0.125,2.375 L 0.359375,1.125 0.46875,1.09375 C 0.5625,1.144531 0.675781,1.179688 0.8125,1.203125 0.945312,1.234375 1.085938,1.25 1.234375,1.25 1.472656,1.25 1.675781,1.21875 1.84375,1.15625 2.007812,1.09375 2.148438,0.984375 2.265625,0.828125 2.378906,0.679688 2.476562,0.476562 2.5625,0.21875 L 0.125,-6.09375 H 1.734375 L 3.25,-1.859375 h 0.140625 l 1.46875,-4.234375 h 1.5625 L 3.96875,0.375 C 3.769531,0.90625 3.550781,1.328125 3.3125,1.640625 3.082031,1.960938 2.804688,2.203125 2.484375,2.359375 2.171875,2.515625 1.789062,2.59375 1.34375,2.59375 Z m 0,0"
+ id="path644" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g658"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(571.55424,280.96421)"
+ id="g656">
+ <g
+ id="g654">
+ <path
+ d="m 4.203125,-1.453125 0.40625,1.125 C 4.441406,-0.179688 4.234375,-0.0703125 3.984375,0 3.734375,0.0703125 3.445312,0.109375 3.125,0.109375 c -0.65625,0 -1.15625,-0.1757812 -1.5,-0.53125 -0.34375,-0.363281 -0.515625,-0.882813 -0.515625,-1.5625 v -2.90625 H 0.1875 v -1.21875 h 0.921875 v -1.1875 l 1.53125,-0.25 v 1.4375 H 4.375 v 1.21875 H 2.640625 v 2.78125 c 0,0.3125 0.0625,0.539063 0.1875,0.671875 0.125,0.136719 0.304687,0.203125 0.546875,0.203125 0.269531,0 0.507812,-0.070313 0.71875,-0.21875 z m 0,0"
+ id="path652" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g666"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(576.2913,280.96421)"
+ id="g664">
+ <g
+ id="g662">
+ <path
+ d="m 0.875,0 v -8.546875 h 1.53125 v 3.25 l 0.125,0.015625 c 0.195312,-0.300781 0.441406,-0.53125 0.734375,-0.6875 0.300781,-0.164062 0.660156,-0.25 1.078125,-0.25 1.34375,0 2.015625,0.765625 2.015625,2.296875 V 0 h -1.53125 v -3.734375 c 0,-0.414063 -0.085937,-0.71875 -0.25,-0.90625 -0.167969,-0.1875 -0.421875,-0.28125 -0.765625,-0.28125 -0.4375,0 -0.78125,0.148437 -1.03125,0.4375 -0.25,0.28125 -0.375,0.726563 -0.375,1.328125 V 0 Z m 0,0"
+ id="path660" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g674"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(583.43283,280.96421)"
+ id="g672">
+ <g
+ id="g670">
+ <path
+ d="M 3.546875,0.109375 C 2.953125,0.109375 2.425781,-0.0078125 1.96875,-0.25 1.519531,-0.5 1.171875,-0.859375 0.921875,-1.328125 c -0.25,-0.476563 -0.375,-1.050781 -0.375,-1.71875 0,-0.664063 0.125,-1.238281 0.375,-1.71875 0.25,-0.476563 0.597656,-0.835937 1.046875,-1.078125 0.457031,-0.25 0.984375,-0.375 1.578125,-0.375 0.59375,0 1.113281,0.125 1.5625,0.375 0.457031,0.242188 0.8125,0.601562 1.0625,1.078125 0.25,0.480469 0.375,1.054687 0.375,1.71875 0,0.667969 -0.125,1.242187 -0.375,1.71875 -0.25,0.46875 -0.605469,0.828125 -1.0625,1.078125 -0.449219,0.2421875 -0.96875,0.359375 -1.5625,0.359375 z m 0,-1.296875 c 0.945313,0 1.421875,-0.617188 1.421875,-1.859375 0,-0.644531 -0.125,-1.117187 -0.375,-1.421875 -0.242188,-0.300781 -0.589844,-0.453125 -1.046875,-0.453125 -0.949219,0 -1.421875,0.625 -1.421875,1.875 0,1.242187 0.472656,1.859375 1.421875,1.859375 z m 0,0"
+ id="path668" />
+ </g>
+ </g>
+ </g>
+ <g
+ fill="#ffffff"
+ fill-opacity="1"
+ id="g682"
+ transform="translate(-43.488732,-201.52699)">
+ <g
+ transform="translate(590.51908,280.96421)"
+ id="g680">
+ <g
+ id="g678">
+ <path
+ d="m 0.875,0 v -6.09375 h 1.46875 v 0.890625 l 0.125,0.03125 c 0.375,-0.695313 0.988281,-1.046875 1.84375,-1.046875 0.707031,0 1.222656,0.195312 1.546875,0.578125 0.332031,0.386719 0.5,0.945313 0.5,1.671875 V 0 h -1.53125 v -3.78125 c 0,-0.40625 -0.085937,-0.695312 -0.25,-0.875 C 4.421875,-4.832031 4.164062,-4.921875 3.8125,-4.921875 3.363281,-4.921875 3.015625,-4.78125 2.765625,-4.5 2.523438,-4.21875 2.40625,-3.769531 2.40625,-3.15625 V 0 Z m 0,0"
+ id="path676" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/sources/shiboken6/doc/images/shibokenqtarch.png b/sources/shiboken6/doc/images/shibokenqtarch.png
index 359413373..c20ba4624 100644
--- a/sources/shiboken6/doc/images/shibokenqtarch.png
+++ b/sources/shiboken6/doc/images/shibokenqtarch.png
Binary files differ
diff --git a/sources/shiboken6/doc/images/shibokenqtarch.svg b/sources/shiboken6/doc/images/shibokenqtarch.svg
index d9212f18c..8f52b8db4 100644
--- a/sources/shiboken6/doc/images/shibokenqtarch.svg
+++ b/sources/shiboken6/doc/images/shibokenqtarch.svg
@@ -2,24 +2,24 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="275"
height="197.55103"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.92.2 2405546, 2018-03-11"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
version="1.0"
sodipodi:docname="shibokenqtarch.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="shibokenqtarch.png"
inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
+ inkscape:export-ydpi="90"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4">
<marker
@@ -54,23 +54,26 @@
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="1.0474359"
- inkscape:cx="110.19617"
- inkscape:cy="69.09871"
+ inkscape:zoom="2.0948718"
+ inkscape:cx="130.07956"
+ inkscape:cy="99.051407"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="1002"
- inkscape:window-height="1042"
- inkscape:window-x="10"
- inkscape:window-y="28"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
showguides="true"
inkscape:guide-bbox="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
- inkscape:window-maximized="0">
+ inkscape:window-maximized="0"
+ inkscape:showpageshadow="2"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid44"
@@ -85,7 +88,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -114,7 +117,7 @@
sodipodi:nodetypes="ccccccc" />
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.68707466px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.12244904;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.6871px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.12245;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
x="120.87232"
y="334.88406"
id="text153"><tspan
@@ -122,10 +125,10 @@
id="tspan151"
x="120.87232"
y="334.88406"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.68707466px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.12244904;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">Qt for Python</tspan></text>
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.6871px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.12245;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">Qt for Python</tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.74510956px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.31862774"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.7451px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.318628"
x="121.09701"
y="354.01886"
id="text157"><tspan
@@ -133,7 +136,7 @@
x="121.09701"
y="354.01886"
id="tspan159"
- style="fill:#ffffff;fill-opacity:1;stroke-width:0.31862774">Qt classes and functions exported to Python</tspan></text>
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0.318628">Qt classes and functions exported to Python</tspan></text>
<path
style="fill:#53586b;fill-opacity:1;stroke:none;stroke-width:2.20567369;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 106.0768,391.19877 v 44.89796 h 262.2093 l 12.7907,-11.22449 V 379.97428 H 117.53514 Z"
@@ -142,7 +145,7 @@
sodipodi:nodetypes="ccccccc" />
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.68707466px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.41717955"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.6871px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.41718"
x="121.0225"
y="403.38095"
id="text153-2"><tspan
@@ -150,10 +153,10 @@
id="tspan151-9"
x="121.0225"
y="403.38095"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.68707466px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.41717955">Shiboken</tspan></text>
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:16.6871px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.41718">Shiboken</tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.74510956px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.31862774"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.7451px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:Titillium;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.318628"
x="121.09701"
y="421.95245"
id="text157-1"><tspan
@@ -161,10 +164,10 @@
x="121.09701"
y="421.95245"
id="tspan159-2"
- style="fill:#ffffff;fill-opacity:1;stroke-width:0.31862774">Generator that exposes C++ classes to Python</tspan></text>
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0.318628">Generator that exposes C++ classes to Python</tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.95918465px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.31862774"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.9592px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.318628"
x="123.35368"
y="482.61551"
id="text157-1-7"><tspan
@@ -172,17 +175,17 @@
x="123.35368"
y="482.61551"
id="tspan159-2-0"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.95918465px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.31862774">CPython API</tspan></text>
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.9592px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.318628">CPython API</tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.95918465px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.4132798"
- x="265.1445"
- y="483.19019"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.9592px;line-height:1.25;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.41328"
+ x="271.38934"
+ y="483.42886"
id="text157-1-9"><tspan
sodipodi:role="line"
- x="265.1445"
- y="483.19019"
+ x="271.38934"
+ y="483.42886"
id="tspan159-2-3"
- style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.95918465px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.4132798">Qt 5 Libraries</tspan></text>
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:17.9592px;font-family:Titillium;-inkscape-font-specification:'Titillium, Semi-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke-width:0.41328">Qt Libraries</tspan></text>
</g>
</svg>
diff --git a/sources/shiboken6/doc/index.rst b/sources/shiboken6/doc/index.rst
index d7cb4c2b1..68f96dded 100644
--- a/sources/shiboken6/doc/index.rst
+++ b/sources/shiboken6/doc/index.rst
@@ -25,73 +25,92 @@ Shiboken
Documentation
=============
-.. panels::
- :body: text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
+.. grid:: 1 3 3 3
+ :gutter: 2
- Install and build from source.
+ .. grid-item-card::
+ :class-item: text-center
- +++
+ Install and build from source.
+ +++
+ .. button-ref:: gettingstarted
+ :color: primary
+ :outline:
+ :expand:
- .. link-button:: gettingstarted
- :type: ref
- :text: Getting Started
- :classes: btn-qt btn-block stretched-link
- ---
+ Getting Started
- Binding generator executable.
+ .. grid-item-card::
+ :class-item: text-center
- +++
+ Binding generator executable.
+ +++
+ .. button-ref:: shibokengenerator
+ :color: primary
+ :outline:
+ :expand:
- .. link-button:: shibokengenerator
- :type: ref
- :text: Shiboken Generator
- :classes: btn-qt btn-block stretched-link
- ---
+ Shiboken Generator
- Python utility module.
+ .. grid-item-card::
+ :class-item: text-center
- +++
+ Python utility module.
+ +++
+ .. button-ref:: shibokenmodule
+ :color: primary
+ :outline:
+ :expand:
- .. link-button:: shibokenmodule
- :type: ref
- :text: Shiboken Module
- :classes: btn-qt btn-block stretched-link
+ Shiboken Module
- ---
+ .. grid-item-card::
+ :class-item: text-center
- Reference and functionallities.
+ Reference and functionallities.
+ +++
+ .. button-ref:: typesystem
+ :color: primary
+ :outline:
+ :expand:
- +++
+ Type System
- .. link-button:: typesystem
- :type: ref
- :text: Type System
- :classes: btn-qt btn-block stretched-link
+ .. grid-item-card::
+ :class-item: text-center
- ---
+ Using Shiboken.
+ +++
+ .. button-ref:: examples/index
+ :color: primary
+ :outline:
+ :expand:
- Using Shiboken.
+ Examples
- +++
+ .. grid-item-card::
+ :class-item: text-center
- .. link-button:: examples/index
- :type: ref
- :text: Examples
- :classes: btn-qt btn-block stretched-link
+ Generating Python stub files.
+ +++
+ .. button-ref:: shiboken-genpyi
+ :color: primary
+ :outline:
+ :expand:
- ---
+ shiboken6-genpyi
- Known issues and FAQ.
+ .. grid-item-card::
+ :class-item: text-center
- +++
-
- .. link-button:: considerations
- :type: ref
- :text: Considerations
- :classes: btn-qt btn-block stretched-link
+ Known issues and FAQ.
+ +++
+ .. button-ref:: considerations
+ :color: primary
+ :outline:
+ :expand:
+ Considerations
.. toctree::
:hidden:
@@ -102,4 +121,5 @@ Documentation
shibokenmodule.rst
typesystem.rst
examples/index.rst
+ shiboken-genpyi.rst
considerations.rst
diff --git a/sources/shiboken6/doc/scripts/patch_qhp.py b/sources/shiboken6/doc/scripts/patch_qhp.py
index c0786d9ab..750789698 100644
--- a/sources/shiboken6/doc/scripts/patch_qhp.py
+++ b/sources/shiboken6/doc/scripts/patch_qhp.py
@@ -3,31 +3,60 @@
import fileinput
import re
+import sys
from argparse import ArgumentParser, RawTextHelpFormatter
-options = ArgumentParser(description='Qhp file updater',
- formatter_class=RawTextHelpFormatter)
-options.add_argument('-f',
- '--filename',
- type=str,
- help='Qhp filename with the relative path.',
- required=True)
-options.add_argument('-v',
- '--vfolder',
- type=str,
- help='String to be injected into the Qhp file.')
-args=options.parse_args()
-
-try:
- for line in fileinput.input(args.filename,inplace=True,backup='.bak'):
- line_copy=line.strip()
- if not line_copy: # check for empty line
- continue
- match=re.match('(^.*virtualFolder.)doc(.*$)',line)
+
+DESC="""Qhp file updater
+
+Replaces virtual folder ids in .qhp files preparing for
+registering the documentation in Qt Assistant."""
+
+
+VIRTUAL_FOLDER_PATTERN = re.compile("(^.*virtualFolder.)doc(.*$)")
+# Strip "PySide6.QtModule." from index entries
+INDEX_CLASS_PATTERN = re.compile(r'^(\s*<keyword name=")PySide6\.[^.]+\.(.*\(class in .*)$')
+INDEX_METHOD_PATTERN = re.compile(r'^(\s+<keyword name=".* \()PySide6\.[^.]+\.(.*>)$')
+
+
+virtual_folder = ""
+strip_pyside_module = False
+
+
+def process_line(line):
+ global virtual_folder
+ match = VIRTUAL_FOLDER_PATTERN.match(line)
+ if match:
+ print(f"{match.group(1)}{virtual_folder}{match.group(2)}")
+ return
+ if strip_pyside_module:
+ match = INDEX_METHOD_PATTERN.match(line)
+ if match:
+ print(f"{match.group(1)}{match.group(2)}")
+ return
+ match = INDEX_CLASS_PATTERN.match(line)
if match:
- repl=''.join([match.group(1), args.vfolder, match.group(2)])
- print(line.replace(match.group(0),repl),end=' ')
- else:
- print(line.rstrip())
-except:
- pass
+ print(f"{match.group(1)}{match.group(2)}")
+ return
+ sys.stdout.write(line)
+
+
+if __name__ == '__main__':
+ arg_parser = ArgumentParser(description=DESC,
+ formatter_class=RawTextHelpFormatter)
+ arg_parser.add_argument('-v', '--vfolder', type=str,
+ help='String to be injected into the Qhp file.')
+ arg_parser.add_argument("--pyside", "-p", action="store_true",
+ help="Strip the PySide module path off the index entries.")
+ arg_parser.add_argument("file", type=str, help='Qhp filename.')
+ options = arg_parser.parse_args()
+ virtual_folder = options.vfolder
+ strip_pyside_module = options.pyside
+
+ try:
+ with fileinput.input(options.file, inplace=True,
+ backup=".bak") as fh:
+ for line in fh:
+ process_line(line)
+ except Exception as e:
+ print(f"WARNING: patch_qhp.py failed: {e}", file=sys.stderr)
diff --git a/sources/shiboken6/doc/shiboken-genpyi.rst b/sources/shiboken6/doc/shiboken-genpyi.rst
new file mode 100644
index 000000000..44d0edb97
--- /dev/null
+++ b/sources/shiboken6/doc/shiboken-genpyi.rst
@@ -0,0 +1,32 @@
+.. _shiboken6-genpyi:
+
+shiboken6-genpyi
+================
+
+`shiboken6-genpyi` is a command line tool to generate Python stub files
+(.pyi) for any shiboken binding-based module (not just PySide). Stub
+files define signatures of all classes, methods (including overloads),
+constants and enums of a module. Signatures also contain type hints.
+This helps your module integrate with Python type checkers and IDEs.
+For example, if you use any function from your module, your IDE's
+function lookup feature will show you the function signature and its
+parameters and return value including types.
+
+
+Usage
+-----
+
+To generate stub files for a module, run the following command:
+
+.. code-block:: bash
+
+ shiboken6-genpyi <module_names> [OPTIONS]
+
+where `<module_names>` is a space-separated list of module names (the
+modules must be importable from the working directory) and where
+`[OPTIONS]` can be one of the following:
+
+* **--quiet**: Run the tool quietly without output to stdout.
+* **--outpath <output_dir>**: Specify the output directory for the
+ generated stub files. If not specified, the stub files are generated
+ in the location of the module binary.
diff --git a/sources/shiboken6/doc/shibokengenerator.rst b/sources/shiboken6/doc/shibokengenerator.rst
index d42827c0e..14340ab69 100644
--- a/sources/shiboken6/doc/shibokengenerator.rst
+++ b/sources/shiboken6/doc/shibokengenerator.rst
@@ -52,13 +52,13 @@ Handwritten inputs
Creating new bindings involves creating several pieces of "code": the header,
the typesystem and, in most cases, the injected code.
-:header: A header with ``#include`` directives listing all the headers of the
- desired classes. This header is not referenced by the generated code.
- Alternatively, it is possible to pass a list of the headers of the
- desired classes directly on the command line. In this case,
- the command line option ``--use-global-header`` should be passed as
- well to prevent the headers from being suppressed in the generated
- code.
+**header** A header with ``#include`` directives listing all the headers of the
+ desired classes. This header is not referenced by the generated code.
+ Alternatively, it is possible to pass a list of the headers of the
+ desired classes directly on the command line. In this case,
+ the command line option ``--use-global-header`` should be passed as
+ well to prevent the headers from being suppressed in the generated
+ code.
::ref:`typesystem`: XML files that provides the developer with a tool to customize the
way that the generators will see the classes and functions. For
@@ -112,17 +112,25 @@ Options
``--avoid-protected-hack``
Avoid the use of the '#define protected public' hack.
-.. _use-isnull-as-nb-nonzero:
+.. _use-isnull-as-nb-bool:
-``--use-isnull-as-nb_nonzero``
+``--use-isnull-as-nb-bool``
If a class has an isNull() const method, it will be used to
compute the value of boolean casts (see :ref:`bool-cast`).
+ The legacy option ``--use-isnull-as-nb_nonzero`` has the
+ same effect, but should not be used any more.
-.. _use-operator-bool-as-nb-nonzero:
+``--lean-headers``
+ Forward declare classes in module headers instead of including their class
+ headers where possible.
-``--use-operator-bool-as-nb_nonzero``
+.. _use-operator-bool-as-nb-bool:
+
+``--use-operator-bool-as-nb-bool``
If a class has an operator bool, it will be used to compute
the value of boolean casts (see :ref:`bool-cast`).
+ The legacy option ``--use-operator-bool-as-nb_nonzero`` has the
+ same effect, but should not be used any more.
.. _no-implicit-conversions:
@@ -194,12 +202,21 @@ Options
When '-' is passed as the first option in the list, none of the options
built into shiboken will be added, allowing for a complete replacement.
+``--compiler=<type>``
+ Emulated compiler type (g++, msvc, clang)
+
+``--compiler-path=<file>``
+ Path to the compiler for determining builtin include paths
+
+``--platform=<file>``
+ Emulated platform (windows, darwin, unix)
+
.. _include-paths:
``-I<path>, --include-paths=<path>[:<path>:...]``
Include paths used by the C++ parser.
-... _system-include-paths:
+.. _system-include-paths:
``-isystem<path>, --system-include-paths=<path>[:<path>:...]``
System include paths used by the C++ parser
@@ -209,6 +226,12 @@ Options
``-F<path>, --framework-include-paths=<path>[:<path>:...]``
Framework include paths used by the C++ parser
+.. _force-process-system-include-paths:
+
+``--force-process-system-include-paths=<path>[:<path>:...]``
+ Include paths that are considered as system headers by the C++ parser,
+ but should still be processed to extract types
+
.. _language-level:
``--language-level=, -std=<level>``
@@ -234,6 +257,10 @@ Options
``--no-suppress-warnings``
Show all warnings.
+``--log-unmatched``
+ Prints :ref:`suppress-warning` and :ref:`rejection` elements that were
+ not matched. This is useful for cleaning up old type system files.
+
.. _silent:
``--silent``
@@ -249,6 +276,9 @@ Options
``--help``
Display this help and exit.
+``--print-builtin-types``
+ Print information about builtin types
+
.. _version:
``--version``
@@ -289,6 +319,12 @@ QtDocGenerator Options
List of additional XML files to be converted to .rst files
(for example, tutorials).
+``--inheritance-file=<file>``
+ Generate a JSON file containing the class inheritance.
+
+``--disable-inheritance-diagram``
+ Disable the generation of the inheritance diagram.
+
.. _project-file:
********************
@@ -306,18 +342,18 @@ The project file structure
Here follows a comprehensive example of a generator project file.
- .. code-block:: ini
+.. code-block:: ini
- [generator-project]
- generator-set = path/to/generator/CHOICE_GENERATOR
- header-file = DIR/global.h" />
- typesystem-file = DIR/typesystem_for_your_binding.xml
- output-directory location="OUTPUTDIR" />
- include-path = path/to/library/being/wrapped/headers/1
- include-path = path/to/library/being/wrapped/headers/2
- typesystem-path = path/to/directory/containing/type/system/files/1
- typesystem-path = path/to/directory/containing/type/system/files/2
- enable-parent-ctor-heuristic
+ [generator-project]
+ generator-set = path/to/generator/CHOICE_GENERATOR
+ header-file = DIR/global.h" />
+ typesystem-file = DIR/typesystem_for_your_binding.xml
+ output-directory location="OUTPUTDIR" />
+ include-path = path/to/library/being/wrapped/headers/1
+ include-path = path/to/library/being/wrapped/headers/2
+ typesystem-path = path/to/directory/containing/type/system/files/1
+ typesystem-path = path/to/directory/containing/type/system/files/2
+ enable-parent-ctor-heuristic
Project file tags
@@ -333,26 +369,25 @@ generator project file following simple conversion rules.
For tags without options, just write as an empty tag without any attributes.
Example:
- .. code-block:: bash
+.. code-block:: bash
- --BOOLEAN-ARGUMENT
+ --BOOLEAN-ARGUMENT
becomes
- .. code-block:: ini
+.. code-block:: ini
- BOOLEAN-ARGUMENT
+ BOOLEAN-ARGUMENT
and
- .. code-block:: bash
+.. code-block:: bash
- --VALUE-ARGUMENT=VALUE
+ --VALUE-ARGUMENT=VALUE
becomes
- .. code-block:: ini
-
- VALUE-ARGUMENT = VALUE
+.. code-block:: ini
+ VALUE-ARGUMENT = VALUE
diff --git a/sources/shiboken6/doc/shibokenmodule.rst b/sources/shiboken6/doc/shibokenmodule.rst
index d6bb12653..3bc4fa6ba 100644
--- a/sources/shiboken6/doc/shibokenmodule.rst
+++ b/sources/shiboken6/doc/shibokenmodule.rst
@@ -1,4 +1,4 @@
-. module:: shiboken
+.. module:: Shiboken
.. |maya| unicode:: Maya U+2122
@@ -19,6 +19,7 @@ Functions
* def :meth:`isOwnedByPython<shiboken.isOwnedByPython>` (obj)
* def :meth:`wasCreatedByPython<shiboken.wasCreatedByPython>` (obj)
* def :meth:`dump<shiboken.dump>` (obj)
+ * def :meth:`disassembleFrame<shiboken.disassembleFrame>` (marker)
Detailed description
^^^^^^^^^^^^^^^^^^^^
@@ -31,6 +32,11 @@ or just for debug purposes.
Some function description refer to "Shiboken based objects", wich means
Python objects instances of any Python Type created using Shiboken.
+To import the module:
+
+.. code-block:: python
+
+ from shiboken6 import Shiboken
.. function:: isValid(obj)
@@ -78,4 +84,64 @@ Python objects instances of any Python Type created using Shiboken.
creating their own bindings as no guarantee is provided that
the string format will be the same across different versions.
- If the object is not a Shiboken based object, a TypeError is thrown.
+ If the object is not a Shiboken based object, a message is printed.
+
+.. function:: disassembleFrame(label)
+
+ Prints the current executing Python frame to stdout and flushes.
+ The disassembly is decorated by some label. Example:
+
+ .. code-block:: python
+
+ lambda: 42
+
+ is shown from inside C++ as
+
+ .. code-block:: c
+
+ <label> BEGIN
+ 1 0 LOAD_CONST 1 (42)
+ 2 RETURN_VALUE
+ <label> END
+
+ When you want to set a breakpoint at the `disassembleFrame` function
+ and you use it from C++, you use the pure function name.
+
+ When you want to use it from Python, you can insert it into your Python
+ code and then maybe instead set a breakpoint at `SbkShibokenModule_disassembleFrame`
+ which is the generated wrapper.
+
+ `label` is a simple string in C++. In Python, you can use any object;
+ internally the `str` function is called with it.
+
+ This method should be used **only** for debug purposes by developers.
+
+ .. function:: dumpTypeGraph(file_name)
+
+ Dumps the inheritance graph of the types existing in libshiboken
+ to ``.dot`` file for use with `Graphviz <https://graphviz.org/>`_.
+
+.. function:: dumpWrapperMap()
+
+ Dumps the map of wrappers existing in libshiboken to standard error.
+
+.. function:: dumpConverters()
+
+ Dumps the map of named converters existing in libshiboken to standard
+ error.
+
+ .. py:class:: VoidPtr(address, size = -1, writeable = 0)
+
+ :param address: (PyBuffer, SbkObject, int, VoidPtr)
+ :param size: int
+ :param writeable: int
+
+ Represents a chunk of memory by address and size and implements the ``buffer`` protocol.
+ It can be constructed from a ``buffer``, a Shiboken based object, a memory address
+ or another VoidPtr instance.
+
+ .. py:method:: toBytes()
+
+ :rtype: bytes
+
+ Returns the contents as ``bytes``.
diff --git a/sources/shiboken6/doc/typediscovery.rst b/sources/shiboken6/doc/typediscovery.rst
new file mode 100644
index 000000000..76d3adf7b
--- /dev/null
+++ b/sources/shiboken6/doc/typediscovery.rst
@@ -0,0 +1,145 @@
+.. _typediscovery:
+
+**************
+Type Discovery
+**************
+
+When converting objects which are part of a class hierarchy from a pointer to a
+base class, it is expected to get the Python type of the actual, most derived
+type, as opposed to C++ which requires a cast for this:
+
+.. code-block:: python
+
+ def event(self, event):
+ if event.type() == QEvent.Type.MousePress:
+ self.do_things(event.position())
+ ...
+
+
+.. code-block:: c++
+
+ bool event(QEvent *event) override
+ {
+ if (event->type() == QEvent::MousePress) {
+ auto *mouseEvent = static_cast<QMouseEvent *>(event);
+ doThings(mouseEvent->position());
+ ...
+ }
+
+The process of determining the type of the event is called `type discovery`.
+
+Shiboken generates code to automatically detect the type. First, it tries to
+find a converter for the name obtained by ``typeid(*pointer).name()``. This
+should normally work as this name is registered by the binding. If that fails,
+it starts walking a type inheritance graph built up in libshiboken to find the
+most derived class by using a cast function (``dynamic_cast<>`` by default) to
+check.
+
+For normal class hierarchies with virtual destructors, no special handling
+is required since ``typeid()`` usually detects the proper class name.
+
+Multiple inheritance
+====================
+
+In case of multiple inheritance in C++, the conversion to the derived class is
+not done in case it is not a single-line direct inheritance. For example, in
+Qt, the class ``QWidget`` inherits both ``QObject`` (base of the ``QObject``
+hierarchy) and ``QPaintDevice``.
+
+When calling a function returning a ``QPaintDevice *``, for example
+``QPainter.device()``, a Python type representing ``QPaintDevice`` is returned
+instead of the underlying widget type. This restriction exists because the
+underlying pointer in C++ is a pointer to a ``QPaintDevice *`` and differs from
+the pointer to the ``QWidget``.
+
+Hierarchies of classes with non-virtual destructors
+===================================================
+
+There are some hierarchies of value-ish C++ classes that do not have virtual
+destructors. This makes type discovery based on ``typeid()`` and
+``dynamic_cast<>`` impossible.
+
+Examples in Qt are the ``QStyleOption``-derived or the ``QGradient``
+-derived classes.
+
+For such classes, some attributes need to be specified on the type entries:
+
+Primarily, a :ref:`polymorphic-id-expression` attribute
+must be specified to be used as a check replacing ``dynamic_cast<>``.
+
+In addition, a :ref:`polymorphic-name-function` attribute can be specified.
+This replaces the type name guess obtained by ``typeid()`` and is mainly a hint
+to speed things up by skipping the checks for each type in the inheritance
+graph.
+
+A :ref:`polymorphic-base` attribute identifies the base class of a hierarchy.
+It should be given in case the base class inherits from another class to
+prevent the logic from going below the base class.
+
+Using type discovery attributes for class hierarchies with virtual destructors
+==============================================================================
+
+It is possible to use :ref:`polymorphic-id-expression` and
+:ref:`polymorphic-name-function` for normal class hierarchies with virtual
+destructors as well since they basically replace ``typeid()`` and
+``dynamic_cast<>``. This makes sense if expressions can be specified that are
+faster than the checks on virtual tables.
+
+Specifying :ref:`polymorphic-base` can also make sense for generating special
+cast functions in case of multiple inheritance. For example, in Qt,
+``QWindow``, ``QLayout``, ``QWidget`` are base classes of hierarchies. Since
+they all inherit from ``QObject``, indicating the base classes prevents
+the logic from using ``QObject`` as a base class.
+
+.. _typediscovery-attributes:
+
+Type discovery attributes reference
+===================================
+
+The following attributes related to type discovery may be be specified on the
+:ref:`object-type` or :ref:`value-type` elements:
+
+.. _polymorphic-id-expression:
+
+polymorphic-id-expression
++++++++++++++++++++++++++
+
+The **polymorphic-id-expression** attribute specifies an expression checking
+whether a base class pointer is of the matching type. For example, in a
+``virtual eventHandler(BaseEvent *e)`` function, this is used to construct a
+Python wrapper matching the derived class (for example, a ``MouseEvent`` or
+similar). The attribute value may contain placeholders:
+
+%1
+ Fully qualified class name
+
+%B
+ Fully qualified name of the base class (found by base class
+ search or as indicated by **polymorphic-base**).
+
+To check for a class inheriting ``BaseEvent``, specify:
+
+.. code-block:: xml
+
+ <object-type name="MouseEvent"
+ polymorphic-id-expression="%B-&gt;type() == BaseEvent::MouseEvent"/>
+
+.. _polymorphic-name-function:
+
+polymorphic-name-function
++++++++++++++++++++++++++
+
+The **polymorphic-name-function** attribute specifies the name of a function
+returning the type name of a derived class on the base class type entry.
+Normally, ``typeid(ptr).name()`` is used for this.
+
+The function is expected to return ``const char *``.
+
+.. _polymorphic-base:
+
+polymorphic-base
+++++++++++++++++
+
+The boolean **polymorphic-base** attribute indicates whether the class is the
+base class of a class hierarchy. It is used for the *%B* placeholder in
+**polymorphic-id-expression** and for cast operations in multiple inheritance.
diff --git a/sources/shiboken6/doc/typesystem.rst b/sources/shiboken6/doc/typesystem.rst
index e1e4fdda2..26f929801 100644
--- a/sources/shiboken6/doc/typesystem.rst
+++ b/sources/shiboken6/doc/typesystem.rst
@@ -65,3 +65,4 @@ Extra options and Python caveats
typesystem_solving_compilation.rst
typesystem_specialfunctions.rst
+ typediscovery.rst
diff --git a/sources/shiboken6/doc/typesystem_arguments.rst b/sources/shiboken6/doc/typesystem_arguments.rst
index b6967e721..d950b6c32 100644
--- a/sources/shiboken6/doc/typesystem_arguments.rst
+++ b/sources/shiboken6/doc/typesystem_arguments.rst
@@ -8,77 +8,77 @@ Modifying Arguments
conversion-rule
^^^^^^^^^^^^^^^
- The ``conversion-rule`` node allows you to write customized code to convert
- the given argument between the target language and C++.
- It is then a child of the :ref:`modify-argument` node:
+The ``conversion-rule`` node allows you to write customized code to convert
+the given argument between the target language and C++.
+It is then a child of the :ref:`modify-argument` node:
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="2">
- <!-- for the second argument of the function -->
- <conversion-rule class="target | native">
- // the code
- </conversion-rule>
- </modify-argument>
+ <modify-argument index="2">
+ <!-- for the second argument of the function -->
+ <conversion-rule class="target | native">
+ // the code
+ </conversion-rule>
+ </modify-argument>
- The ``class`` attribute accepts one of the following values to define the
- conversion direction to be either ``target-to-native`` or ``native-to-target``:
+The ``class`` attribute accepts one of the following values to define the
+conversion direction to be either ``target-to-native`` or ``native-to-target``:
- * ``native``: Defines the conversion direction to be ``target-to-native``.
- It is similar to the existing ``<target-to-native>`` element.
- See :ref:`Conversion Rule Tag <conversion-rule-tag>` for more information.
+* ``native``: Defines the conversion direction to be ``target-to-native``.
+ It is similar to the existing ``<target-to-native>`` element.
+ See :ref:`Conversion Rule Tag <conversion-rule-tag>` for more information.
- * ``target``: Defines the conversion direction to be ``native-to-target``.
- It is similar to the existing ``<native-to-target>`` element.
- See :ref:`Conversion Rule Tag <conversion-rule-tag>` for more information.
+* ``target``: Defines the conversion direction to be ``native-to-target``.
+ It is similar to the existing ``<native-to-target>`` element.
+ See :ref:`Conversion Rule Tag <conversion-rule-tag>` for more information.
- This node is typically used in combination with the :ref:`replace-type` and
- :ref:`remove-argument` nodes. The given code is used instead of the generator's
- conversion code.
+This node is typically used in combination with the :ref:`replace-type` and
+:ref:`remove-argument` nodes. The given code is used instead of the generator's
+conversion code.
- Writing %N in the code (where N is a number), will insert the name of the
- nth argument. Alternatively, %in and %out which will be replaced with the
- name of the conversion's input and output variable, respectively. Note the
- output variable must be declared explicitly, for example:
+Writing %N in the code (where N is a number), will insert the name of the
+nth argument. Alternatively, %in and %out which will be replaced with the
+name of the conversion's input and output variable, respectively. Note the
+output variable must be declared explicitly, for example:
- .. code-block:: xml
+.. code-block:: xml
- <conversion-rule class="native">
- bool %out = (bool) %in;
- </conversion-rule>
+ <conversion-rule class="native">
+ bool %out = (bool) %in;
+ </conversion-rule>
- .. note::
+.. note::
- You can also use the ``conversion-rule`` node to specify
- :ref:`a conversion code which will be used instead of the generator's conversion code everywhere for a given type <conversion-rule-tag>`.
+ You can also use the ``conversion-rule`` node to specify
+ :ref:`a conversion code which will be used instead of the generator's conversion code everywhere for a given type <conversion-rule-tag>`.
.. _remove-argument:
remove-argument
^^^^^^^^^^^^^^^
- The ``remove-argument`` node removes the given argument from the function's
- signature, and it is a child of the :ref:`modify-argument` node.
+The ``remove-argument`` node removes the given argument from the function's
+signature, and it is a child of the :ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument>
- <remove-argument />
- </modify-argument>
+ <modify-argument>
+ <remove-argument />
+ </modify-argument>
.. _rename-to:
rename to
^^^^^^^^^
- The ``rename to`` node is used to rename a argument and use this new name in
- the generated code, and it is a child of the :ref:`modify-argument` node.
+The ``rename to`` node is used to rename a argument and use this new name in
+the generated code, and it is a child of the :ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument>
- <rename to='...' />
- </modify-argument>
+ <modify-argument>
+ <rename to='...' />
+ </modify-argument>
.. warning:: This tag is deprecated, use the ``rename`` attribute from :ref:`modify-argument` tag instead.
@@ -87,143 +87,143 @@ rename to
remove-default-expression
^^^^^^^^^^^^^^^^^^^^^^^^^
- The ``remove-default-expression`` node disables the use of the default expression
- for the given argument, and it is a child of the :ref:`modify-argument` node.
+The ``remove-default-expression`` node disables the use of the default expression
+for the given argument, and it is a child of the :ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument...>
- <remove-default-expression />
- </modify-argument>
+ <modify-argument...>
+ <remove-default-expression />
+ </modify-argument>
.. _replace-default-expression:
replace-default-expression
^^^^^^^^^^^^^^^^^^^^^^^^^^
- The ``replace-default-expression`` node replaces the specified argument with the
- expression specified by the ``with`` attribute, and it is a child of the
- :ref:`modify-argument` node.
+The ``replace-default-expression`` node replaces the specified argument with the
+expression specified by the ``with`` attribute, and it is a child of the
+:ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument>
- <replace-default-expression with="..." />
- </modify-argument>
+ <modify-argument>
+ <replace-default-expression with="..." />
+ </modify-argument>
.. _replace-type:
replace-type
^^^^^^^^^^^^
- The ``replace-type`` node replaces the type of the given argument to the one
- specified by the ``modified-type`` attribute, and it is a child of the
- :ref:`modify-argument` node.
+The ``replace-type`` node replaces the type of the given argument to the one
+specified by the ``modified-type`` attribute, and it is a child of the
+:ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument>
- <replace-type modified-type="..." />
- </modify-argument>
+ <modify-argument>
+ <replace-type modified-type="..." />
+ </modify-argument>
- If the new type is a class, the ``modified-type`` attribute must be set to
- the fully qualified name (including name of the package as well as the class
- name).
+If the new type is a class, the ``modified-type`` attribute must be set to
+the fully qualified name (including name of the package as well as the class
+name).
.. _define-ownership:
define-ownership
^^^^^^^^^^^^^^^^
- The ``define-ownership`` tag indicates that the function changes the ownership
- rules of the argument object, and it is a child of the
- :ref:`modify-argument` node.
- The ``class`` attribute specifies the class of
- function where to inject the ownership altering code
- (see :ref:`codegenerationterminology`). The ``owner`` attribute
- specifies the new ownership of the object. It accepts the following values:
-
- * target: the target language will assume full ownership of the object.
- The native resources will be deleted when the target language
- object is finalized.
- * c++: The native code assumes full ownership of the object. The target
- language object will not be garbage collected.
- * default: The object will get default ownership, depending on how it
- was created.
-
- .. code-block:: xml
-
- <modify-argument>
- <define-ownership class="target | native"
- owner="target | c++ | default" />
- </modify-argument>
+The ``define-ownership`` tag indicates that the function changes the ownership
+rules of the argument object, and it is a child of the
+:ref:`modify-argument` node.
+The ``class`` attribute specifies the class of
+function where to inject the ownership altering code
+(see :ref:`codegenerationterminology`). The ``owner`` attribute
+specifies the new ownership of the object. It accepts the following values:
+
+* target: the target language will assume full ownership of the object.
+ The native resources will be deleted when the target language
+ object is finalized.
+* c++: The native code assumes full ownership of the object. The target
+ language object will not be garbage collected.
+* default: The object will get default ownership, depending on how it
+ was created.
+
+.. code-block:: xml
+
+ <modify-argument>
+ <define-ownership class="target | native"
+ owner="target | c++ | default" />
+ </modify-argument>
.. _reference-count:
reference-count
^^^^^^^^^^^^^^^
- The ``reference-count`` tag dictates how an argument should be handled by the
- target language reference counting system (if there is any), it also indicates
- the kind of relationship the class owning the function being modified has with
- the argument. It is a child of the :ref:`modify-argument` node.
- For instance, in a model/view relation a view receiving a model
- as argument for a **setModel** method should increment the model's reference
- counting, since the model should be kept alive as much as the view lives.
- Remember that out hypothetical view could not become parent of the model,
- since the said model could be used by other views as well.
- The ``action`` attribute specifies what should be done to the argument
- reference counting when the modified method is called. It accepts the
- following values:
-
- * add: increments the argument reference counter.
- * add-all: increments the reference counter for each item in a collection.
- * remove: decrements the argument reference counter.
- * set: will assign the argument to the variable containing the reference.
- * ignore: does nothing with the argument reference counter
- (sounds worthless, but could be used in situations
- where the reference counter increase is mandatory
- by default).
-
- .. code-block:: xml
-
- <modify-argument>
- <reference-count action="add|add-all|remove|set|ignore" variable-name="..." />
- </modify-argument>
-
-
- The variable-name attribute specifies the name used for the variable that
- holds the reference(s).
+The ``reference-count`` tag dictates how an argument should be handled by the
+target language reference counting system (if there is any), it also indicates
+the kind of relationship the class owning the function being modified has with
+the argument. It is a child of the :ref:`modify-argument` node.
+For instance, in a model/view relation a view receiving a model
+as argument for a **setModel** method should increment the model's reference
+counting, since the model should be kept alive as much as the view lives.
+Remember that out hypothetical view could not become parent of the model,
+since the said model could be used by other views as well.
+The ``action`` attribute specifies what should be done to the argument
+reference counting when the modified method is called. It accepts the
+following values:
+
+* add: increments the argument reference counter.
+* add-all: increments the reference counter for each item in a collection.
+* remove: decrements the argument reference counter.
+* set: will assign the argument to the variable containing the reference.
+* ignore: does nothing with the argument reference counter
+ (sounds worthless, but could be used in situations
+ where the reference counter increase is mandatory
+ by default).
+
+.. code-block:: xml
+
+ <modify-argument>
+ <reference-count action="add|add-all|remove|set|ignore" variable-name="..." />
+ </modify-argument>
+
+
+The variable-name attribute specifies the name used for the variable that
+holds the reference(s).
.. _replace-value:
replace-value
^^^^^^^^^^^^^
- The ``replace-value`` attribute lets you replace the return statement of a
- function with a fixed string. This attribute can only be used for the
- argument at ``index`` 0, which is always the function's return value.
+The ``replace-value`` attribute lets you replace the return statement of a
+function with a fixed string. This attribute can only be used for the
+argument at ``index`` 0, which is always the function's return value.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="0" replace-value="this"/>
+ <modify-argument index="0" replace-value="this"/>
.. _parent:
parent
^^^^^^
- The ``parent`` node lets you define the argument parent which will
- take ownership of argument and will destroy the C++ child object when the
- parent is destroyed (see :ref:`ownership-parent`).
- It is a child of the :ref:`modify-argument` node.
+The ``parent`` node lets you define the argument parent which will
+take ownership of argument and will destroy the C++ child object when the
+parent is destroyed (see :ref:`ownership-parent`).
+It is a child of the :ref:`modify-argument` node.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="1">
- <parent index="this" action="add | remove" />
- </modify-argument>
+ <modify-argument index="1">
+ <parent index="this" action="add | remove" />
+ </modify-argument>
- In the ``index`` argument you must specify the parent argument. The action
- *add* creates a parent link between objects, while *remove* will undo the
- parentage relationship.
+In the ``index`` argument you must specify the parent argument. The action
+*add* creates a parent link between objects, while *remove* will undo the
+parentage relationship.
diff --git a/sources/shiboken6/doc/typesystem_builtin_types.rst b/sources/shiboken6/doc/typesystem_builtin_types.rst
index ba9a576a6..dea253930 100644
--- a/sources/shiboken6/doc/typesystem_builtin_types.rst
+++ b/sources/shiboken6/doc/typesystem_builtin_types.rst
@@ -26,6 +26,20 @@ on platform.
`std::string`, `std::wstring` and their associated view types
`std::string_view`, `std::wstring_view` are also supported.
+
+.. _builtin-cpp-container-types:
+
+C++ Container Types
+^^^^^^^^^^^^^^^^^^^
+
+The C++ containers ``std::list``\, ``std::vector``\,
+``std::pair``\, ``std::map``\, ``std::span`` and ``std::unordered_map`` are
+built-in.
+To specify :ref:`opaque-containers`, use the :ref:`opaque-container` element.
+:ref:`container-type` can still be specified to modify the built-in behavior.
+For this case, a number of pre-defined conversion templates
+are provided (see :ref:`predefined_templates`).
+
.. _cpython-types:
CPython Types
diff --git a/sources/shiboken6/doc/typesystem_codeinjection.rst b/sources/shiboken6/doc/typesystem_codeinjection.rst
index 055e876a8..03d5f4b16 100644
--- a/sources/shiboken6/doc/typesystem_codeinjection.rst
+++ b/sources/shiboken6/doc/typesystem_codeinjection.rst
@@ -12,11 +12,11 @@ should be written to depends upon the technology used on the generated binding c
This is the ``inject-code`` tag options that matters to |project|.
- .. code-block:: xml
+.. code-block:: xml
- <inject-code class="native | target" position="beginning | end">
- // custom code
- </inject-code>
+ <inject-code class="native | target" position="beginning | end">
+ // custom code
+ </inject-code>
inject-code tag
@@ -30,76 +30,79 @@ The ``position`` attribute specifies the location of the custom code in the
function.
- +---------------+------+-----------+--------------------------------------------------------------+
- |Parent Tag |Class |Position |Meaning |
- +===============+======+===========+==============================================================+
- |value-type, |native|beginning |Write to the beginning of a class wrapper ``.cpp`` file, right|
- |object-type | | |after the ``#include`` clauses. A common use would be to write|
- | | | |prototypes for custom functions whose definitions are put on a|
- | | | |``native/end`` code injection. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |Write to the end of a class wrapper ``.cpp`` file. Could be |
- | | | |used to write custom/helper functions definitions for |
- | | | |prototypes declared on ``native/beginning``. |
- | +------+-----------+--------------------------------------------------------------+
- | |target|beginning |Put custom code on the beginning of the wrapper initializer |
- | | | |function (``init_CLASS(PyObject *module)``). This could be |
- | | | |used to manipulate the ``PyCLASS_Type`` structure before |
- | | | |registering it on Python. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |Write the given custom code at the end of the class wrapper |
- | | | |initializer function (``init_CLASS(PyObject *module)``). The |
- | | | |code here will be executed after all the wrapped class |
- | | | |components have been initialized. |
- +---------------+------+-----------+--------------------------------------------------------------+
- |modify-function|native|beginning |Code here is put on the virtual method override of a C++ |
- | | | |wrapper class (the one responsible for passing C++ calls to a |
- | | | |Python override, if there is any), right after the C++ |
- | | | |arguments have been converted but before the Python call. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |This code injection is put in a virtual method override on the|
- | | | |C++ wrapper class, after the call to Python and before |
- | | | |dereferencing the Python method and tuple of arguments. |
- | +------+-----------+--------------------------------------------------------------+
- | |target|beginning |This code is injected on the Python method wrapper |
- | | | |(``PyCLASS_METHOD(...)``), right after the decisor have found |
- | | | |which signature to call and also after the conversion of the |
- | | | |arguments to be used, but before the actual call. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |This code is injected on the Python method wrapper |
- | | | |(``PyCLASS_METHOD(...)``), right after the C++ method call, |
- | | | |but still inside the scope created by the overload for each |
- | | | |signature. |
- | +------+-----------+--------------------------------------------------------------+
- | |shell |declaration|Used only for virtual functions. This code is injected at the |
- | | | |top. |
- | | +-----------+--------------------------------------------------------------+
- | | |beginning |Used only for virtual functions. The code is injected when the|
- | | | |function does not has a Python implementation, then the code |
- | | | |is inserted before c++ call |
- | | +-----------+--------------------------------------------------------------+
- | | |end |Same as above, but the code is inserted after c++ call |
- +---------------+------+-----------+--------------------------------------------------------------+
- |typesystem |native|beginning |Write code to the beginning of the module ``.cpp`` file, right|
- | | | |after the ``#include`` clauses. This position has a similar |
- | | | |purpose as the ``native/beginning`` position on a wrapper |
- | | | |class ``.cpp`` file, namely write function prototypes, but not|
- | | | |restricted to this use. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |Write code to the end of the module ``.cpp`` file. Usually |
- | | | |implementations for function prototypes inserted at the |
- | | | |beginning of the file with a ``native/beginning`` code |
- | | | |injection. |
- | +------+-----------+--------------------------------------------------------------+
- | |target|beginning |Insert code at the start of the module initialization function|
- | | | |(``initMODULENAME()``), before the calling ``Py_InitModule``. |
- | | +-----------+--------------------------------------------------------------+
- | | |end |Insert code at the end of the module initialization function |
- | | | |(``initMODULENAME()``), but before the checking that emits a |
- | | | |fatal error in case of problems importing the module. |
- | | +-----------+--------------------------------------------------------------+
- | | |declaration|Insert code into module header. |
- +---------------+------+-----------+--------------------------------------------------------------+
++---------------+------+-----------+--------------------------------------------------------------+
+|Parent Tag |Class |Position |Meaning |
++===============+======+===========+==============================================================+
+|value-type, |native|beginning |Write to the beginning of a class wrapper ``.cpp`` file, right|
+|object-type | | |after the ``#include`` clauses. A common use would be to write|
+| | | |prototypes for custom functions whose definitions are put on a|
+| | | |``native/end`` code injection. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |Write to the end of a class wrapper ``.cpp`` file. Could be |
+| | | |used to write custom/helper functions definitions for |
+| | | |prototypes declared on ``native/beginning``. |
+| +------+-----------+--------------------------------------------------------------+
+| |target|beginning |Put custom code on the beginning of the wrapper initializer |
+| | | |function (``init_CLASS(PyObject *module)``). This could be |
+| | | |used to manipulate the ``PyCLASS_Type`` structure before |
+| | | |registering it on Python. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |Write the given custom code at the end of the class wrapper |
+| | | |initializer function (``init_CLASS(PyObject *module)``). The |
+| | | |code here will be executed after all the wrapped class |
+| | | |components have been initialized. |
++---------------+------+-----------+--------------------------------------------------------------+
+|modify-function|native|beginning |Code here is put on the virtual method override of a C++ |
+| | | |wrapper class (the one responsible for passing C++ calls to a |
+| | | |Python override, if there is any), right after the C++ |
+| | | |arguments have been converted but before the Python call. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |This code injection is put in a virtual method override on the|
+| | | |C++ wrapper class, after the call to Python and before |
+| | | |dereferencing the Python method and tuple of arguments. |
+| +------+-----------+--------------------------------------------------------------+
+| |target|beginning |This code is injected on the Python method wrapper |
+| | | |(``PyCLASS_METHOD(...)``), right after the decisor have found |
+| | | |which signature to call and also after the conversion of the |
+| | | |arguments to be used, but before the actual call. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |This code is injected on the Python method wrapper |
+| | | |(``PyCLASS_METHOD(...)``), right after the C++ method call, |
+| | | |but still inside the scope created by the overload for each |
+| | | |signature. |
+| +------+-----------+--------------------------------------------------------------+
+| |shell |declaration|Used only for virtual functions. This code is injected at the |
+| | | |top. |
+| | +-----------+--------------------------------------------------------------+
+| | |override |Used only for virtual functions. The code is injected before |
+| | | |the code calling the Python override. |
+| | +-----------+--------------------------------------------------------------+
+| | |beginning |Used only for virtual functions. The code is injected when the|
+| | | |function does not has a Python implementation, then the code |
+| | | |is inserted before c++ call |
+| | +-----------+--------------------------------------------------------------+
+| | |end |Same as above, but the code is inserted after c++ call |
++---------------+------+-----------+--------------------------------------------------------------+
+|typesystem |native|beginning |Write code to the beginning of the module ``.cpp`` file, right|
+| | | |after the ``#include`` clauses. This position has a similar |
+| | | |purpose as the ``native/beginning`` position on a wrapper |
+| | | |class ``.cpp`` file, namely write function prototypes, but not|
+| | | |restricted to this use. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |Write code to the end of the module ``.cpp`` file. Usually |
+| | | |implementations for function prototypes inserted at the |
+| | | |beginning of the file with a ``native/beginning`` code |
+| | | |injection. |
+| +------+-----------+--------------------------------------------------------------+
+| |target|beginning |Insert code at the start of the module initialization function|
+| | | |(``initMODULENAME()``), before the calling ``Py_InitModule``. |
+| | +-----------+--------------------------------------------------------------+
+| | |end |Insert code at the end of the module initialization function |
+| | | |(``initMODULENAME()``), but before the checking that emits a |
+| | | |fatal error in case of problems importing the module. |
+| | +-----------+--------------------------------------------------------------+
+| | |declaration|Insert code into module header. |
++---------------+------+-----------+--------------------------------------------------------------+
Anatomy of Code Injection
@@ -110,16 +113,16 @@ and the places where each kind of code injection goes.
Below is the example C++ class for whom wrapper code will be generated.
- .. code-block:: c++
+.. code-block:: c++
- class InjectCode
- {
- public:
- InjectCode();
- double overloadedMethod(int arg);
- double overloadedMethod(double arg);
- virtual int virtualMethod(int arg);
- };
+ class InjectCode
+ {
+ public:
+ InjectCode();
+ double overloadedMethod(int arg);
+ double overloadedMethod(double arg);
+ virtual int virtualMethod(int arg);
+ };
From the C++ class, |project| will generate a ``injectcode_wrapper.cpp`` file
with the binding code. The next section will use a simplified version of the
@@ -168,21 +171,21 @@ of writing the actual name of the wrapped method/function.
In other words, use
- .. code-block:: xml
+.. code-block:: xml
- <inject-code class="target" position="beginning | end">
- %CPPSELF.originalMethodName();
- </inject-code>
+ <inject-code class="target" position="beginning | end">
+ %CPPSELF.originalMethodName();
+ </inject-code>
instead of
- .. code-block:: xml
+.. code-block:: xml
- <inject-code class="target" position="beginning | end">
- %CPPSELF.%FUNCTION_NAME();
- </inject-code>
+ <inject-code class="target" position="beginning | end">
+ %CPPSELF.%FUNCTION_NAME();
+ </inject-code>
Code Injection for Functions/Methods
@@ -197,30 +200,30 @@ On The Native Side
Notice that this is only used when there is a C++ wrapper, i.e. the wrapped
class is polymorphic.
- .. code-block:: c++
+.. code-block:: c++
- int InjectCodeWrapper::virtualMethod(int arg)
- {
- PyObject *method = BindingManager::instance().getOverride(this, "virtualMethod");
- if (!py_override)
- return this->InjectCode::virtualMethod(arg);
+ int InjectCodeWrapper::virtualMethod(int arg)
+ {
+ PyObject *method = BindingManager::instance().getOverride(this, "virtualMethod");
+ if (!py_override)
+ return this->InjectCode::virtualMethod(arg);
- (... here C++ arguments are converted to Python ...)
+ (... here C++ arguments are converted to Python ...)
- // INJECT-CODE: <modify-function><inject-code class="native" position="beginning">
- // Uses: pre method call custom code, modify the argument before the
- // Python call.
+ // INJECT-CODE: <modify-function><inject-code class="native" position="beginning">
+ // Uses: pre method call custom code, modify the argument before the
+ // Python call.
- (... Python method call goes in here ...)
+ (... Python method call goes in here ...)
- // INJECT-CODE: <modify-function><inject-code class="native" position="end">
- // Uses: post method call custom code, modify the result before delivering
- // it to C++ caller.
+ // INJECT-CODE: <modify-function><inject-code class="native" position="end">
+ // Uses: post method call custom code, modify the result before delivering
+ // it to C++ caller.
- (... Python method and argument tuple are dereferenced here ...)
+ (... Python method and argument tuple are dereferenced here ...)
- return Shiboken::Converter<int>::toCpp(method_result);
- }
+ return Shiboken::Converter<int>::toCpp(method_result);
+ }
On The Target Side
@@ -231,37 +234,37 @@ method that uses an overload decisor to call the correct C++ method based on the
arguments passed by the Python call. Each overloaded method signature has its
own ``beginning`` and ``end`` code injections.
- .. code-block:: c++
+.. code-block:: c++
- static PyObject *PyInjectCode_overloadedMethod(PyObject *self, PyObject *arg)
- {
- PyObject* py_result{};
- if (PyFloat_Check(arg)) {
- double cpp_arg0 = Shiboken::Converter<double >::toCpp(arg);
+ static PyObject *PyInjectCode_overloadedMethod(PyObject *self, PyObject *arg)
+ {
+ PyObject* py_result{};
+ if (PyFloat_Check(arg)) {
+ double cpp_arg0 = Shiboken::Converter<double >::toCpp(arg);
- // INJECT-CODE: <modify-function><inject-code class="target" position="beginning">
- // Uses: pre method call custom code.
+ // INJECT-CODE: <modify-function><inject-code class="target" position="beginning">
+ // Uses: pre method call custom code.
- py_result = Shiboken::Converter<double >::toPython(
- PyInjectCode_cptr(self)->InjectCode::overloadedMethod(cpp_arg0)
- );
+ py_result = Shiboken::Converter<double >::toPython(
+ PyInjectCode_cptr(self)->InjectCode::overloadedMethod(cpp_arg0)
+ );
- // INJECT-CODE: <modify-function><inject-code class="target" position="end">
- // Uses: post method call custom code.
+ // INJECT-CODE: <modify-function><inject-code class="target" position="end">
+ // Uses: post method call custom code.
- } else if (PyNumber_Check(arg)) {
- (... other overload calling code ...)
- } else goto PyInjectCode_overloadedMethod_TypeError;
+ } else if (PyNumber_Check(arg)) {
+ (... other overload calling code ...)
+ } else goto PyInjectCode_overloadedMethod_TypeError;
- if (PyErr_Occurred() || !py_result)
- return {};
+ if (PyErr_Occurred() || !py_result)
+ return {};
- return py_result;
+ return py_result;
- PyInjectCode_overloadedMethod_TypeError:
- PyErr_SetString(PyExc_TypeError, "'overloadedMethod()' called with wrong parameters.");
- return {};
- }
+ PyInjectCode_overloadedMethod_TypeError:
+ PyErr_SetString(PyExc_TypeError, "'overloadedMethod()' called with wrong parameters.");
+ return {};
+ }
.. _codeinjecting_classes:
@@ -277,35 +280,35 @@ On The Native Side
Those injections go in the body of the ``CLASSNAME_wrapper.cpp`` file for the
wrapped class.
- .. code-block:: c++
+.. code-block:: c++
- // Start of ``CLASSNAME_wrapper.cpp``
- #define protected public
- // default includes
- #include <shiboken.h>
- (...)
- #include "injectcode_wrapper.h"
- using namespace Shiboken;
-
- // INJECT-CODE: <value/object-type><inject-code class="native" position="beginning">
- // Uses: prototype declarations
+ // Start of ``CLASSNAME_wrapper.cpp``
+ #define protected public
+ // default includes
+ #include <shiboken.h>
+ (...)
+ #include "injectcode_wrapper.h"
+ using namespace Shiboken;
- (... C++ wrapper virtual methods, if any ...)
+ // INJECT-CODE: <value/object-type><inject-code class="native" position="beginning">
+ // Uses: prototype declarations
- (... Python wrapper code ...)
+ (... C++ wrapper virtual methods, if any ...)
- PyAPI_FUNC(void)
- init_injectcode(PyObject *module)
- {
- (...)
- }
+ (... Python wrapper code ...)
+ PyAPI_FUNC(void)
+ init_injectcode(PyObject *module)
+ {
(...)
+ }
- // INJECT-CODE: <value/object-type><inject-code class="native" position="end">
- // Uses: definition of functions prototyped at ``native/beginning``.
+ (...)
- // End of ``CLASSNAME_wrapper.cpp``
+ // INJECT-CODE: <value/object-type><inject-code class="native" position="end">
+ // Uses: definition of functions prototyped at ``native/beginning``.
+
+ // End of ``CLASSNAME_wrapper.cpp``
.. _codeinjecting_classes_target:
@@ -315,34 +318,34 @@ On The Target Side
Code injections to the class Python initialization function.
- .. code-block:: c++
+.. code-block:: c++
- // Start of ``CLASSNAME_wrapper.cpp``
+ // Start of ``CLASSNAME_wrapper.cpp``
- (...)
+ (...)
- PyAPI_FUNC(void)
- init_injectcode(PyObject *module)
- {
- // INJECT-CODE: <value/object-type><inject-code class="target" position="beginning">
- // Uses: Alter something in the PyInjectCode_Type (tp_flags value for example)
- // before registering it.
+ PyAPI_FUNC(void)
+ init_injectcode(PyObject *module)
+ {
+ // INJECT-CODE: <value/object-type><inject-code class="target" position="beginning">
+ // Uses: Alter something in the PyInjectCode_Type (tp_flags value for example)
+ // before registering it.
- if (PyType_Ready(&PyInjectCode_Type) < 0)
- return;
+ if (PyType_Ready(&PyInjectCode_Type) < 0)
+ return;
- Py_INCREF(&PyInjectCode_Type);
- PyModule_AddObject(module, "InjectCode",
- ((PyObject*)&PyInjectCode_Type));
+ Py_INCREF(&PyInjectCode_Type);
+ PyModule_AddObject(module, "InjectCode",
+ ((PyObject*)&PyInjectCode_Type));
- // INJECT-CODE: <value/object-type><inject-code class="target" position="end">
- // Uses: do something right after the class is registered, like set some static
- // variable injected on this same file elsewhere.
- }
+ // INJECT-CODE: <value/object-type><inject-code class="target" position="end">
+ // Uses: do something right after the class is registered, like set some static
+ // variable injected on this same file elsewhere.
+ }
- (...)
+ (...)
- // End of ``CLASSNAME_wrapper.cpp``
+ // End of ``CLASSNAME_wrapper.cpp``
Code Injection for Modules
==========================
@@ -365,30 +368,30 @@ This is very similar to class wrapper code injections :ref:`codeinjecting_classe
Notice that the inject code at ``target/end`` is inserted before the check for errors
to prevent bad custom code to pass unnoticed.
- .. code-block:: c++
+.. code-block:: c++
- // Start of ``MODULENAME_module_wrapper.cpp``
+ // Start of ``MODULENAME_module_wrapper.cpp``
- (...)
- initMODULENAME()
- {
- // INJECT-CODE: <typesystem><inject-code class="target" position="beginning">
- // Uses: do something before the module is created.
+ (...)
+ initMODULENAME()
+ {
+ // INJECT-CODE: <typesystem><inject-code class="target" position="beginning">
+ // Uses: do something before the module is created.
- PyObject *module = Py_InitModule("MODULENAME", MODULENAME_methods);
+ PyObject *module = Py_InitModule("MODULENAME", MODULENAME_methods);
- (... initialization of wrapped classes, namespaces, functions and enums ...)
+ (... initialization of wrapped classes, namespaces, functions and enums ...)
- // INJECT-CODE: <typesystem><inject-code class="target" position="end">
- // Uses: do something after the module is registered and initialized.
+ // INJECT-CODE: <typesystem><inject-code class="target" position="end">
+ // Uses: do something after the module is registered and initialized.
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module sample");
- }
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module sample");
+ }
- (...)
+ (...)
- // Start of ``MODULENAME_module_wrapper.cpp``
+ // Start of ``MODULENAME_module_wrapper.cpp``
In addition, code can be injected into the module header by specifying ``target``
and ``declaration``. This is useful for type definitions.
diff --git a/sources/shiboken6/doc/typesystem_containers.rst b/sources/shiboken6/doc/typesystem_containers.rst
index 5c4abee44..b5593e20f 100644
--- a/sources/shiboken6/doc/typesystem_containers.rst
+++ b/sources/shiboken6/doc/typesystem_containers.rst
@@ -19,7 +19,8 @@ instead of a Python list. Manipulations like adding or removing elements
can applied directly to them using the C++ container functions.
This is achieved by specifying the name and the instantiated type
-in the ``opaque-containers`` attribute of :ref:`container-type`.
+in the ``opaque-containers`` attribute of :ref:`container-type`
+or using the :ref:`opaque-container` element for existing container types.
A second use case are public fields of container types. In the normal case,
they are converted to Python containers on read access. By a field modification,
@@ -34,41 +35,50 @@ The table below lists the functions supported for opaque sequence containers
besides the sequence protocol (element access via index and ``len()``). Both
the STL and the Qt naming convention (which resembles Python's) are supported:
- +-------------------------------------------+-----------------------------------+
- |Function | Description |
- +-------------------------------------------+-----------------------------------+
- | ``push_back(value)``, ``append(value)`` | Appends *value* to the sequence. |
- +-------------------------------------------+-----------------------------------+
- | ``push_front(value)``, ``prepend(value)`` | Prepends *value* to the sequence. |
- +-------------------------------------------+-----------------------------------+
- | ``clear()`` | Clears the sequence. |
- +-------------------------------------------+-----------------------------------+
- | ``pop_back()``, ``removeLast()`` | Removes the last element. |
- +-------------------------------------------+-----------------------------------+
- | ``pop_front()``, ``removeFirst()`` | Removes the first element. |
- +-------------------------------------------+-----------------------------------+
- | ``reserve(size)`` | For containers that support it |
- | | (``std::vector``, ``QList``), |
- | | allocate memory for at least |
- | | ``size`` elements, preventing |
- | | reallocations. |
- +-------------------------------------------+-----------------------------------+
- | ``capacity()`` | For containers that support it |
- | | (``std::vector``, ``QList``), |
- | | return the number of elements |
- | | that can be stored without |
- | | reallocation. |
- +-------------------------------------------+-----------------------------------+
- | ``data()`` | For containers that support it |
- | | (``std::vector``, ``QList``), |
- | | return a buffer viewing the |
- | | memory. |
- +-------------------------------------------+-----------------------------------+
- | ``constData()`` | For containers that support it |
- | | (``std::vector``, ``QList``), |
- | | return a read-only buffer viewing |
- | | the memory. |
- +-------------------------------------------+-----------------------------------+
++-------------------------------------------+-----------------------------------+
+|Function | Description |
++-------------------------------------------+-----------------------------------+
+| ``push_back(value)``, ``append(value)`` | Appends *value* to the sequence. |
++-------------------------------------------+-----------------------------------+
+| ``push_front(value)``, ``prepend(value)`` | Prepends *value* to the sequence. |
++-------------------------------------------+-----------------------------------+
+| ``clear()`` | Clears the sequence. |
++-------------------------------------------+-----------------------------------+
+| ``pop_back()``, ``removeLast()`` | Removes the last element. |
++-------------------------------------------+-----------------------------------+
+| ``pop_front()``, ``removeFirst()`` | Removes the first element. |
++-------------------------------------------+-----------------------------------+
+| ``reserve(size)`` | For containers that support it |
+| | (``std::vector``, ``QList``), |
+| | allocate memory for at least |
+| | ``size`` elements, preventing |
+| | reallocations. |
++-------------------------------------------+-----------------------------------+
+| ``capacity()`` | For containers that support it |
+| | (``std::vector``, ``QList``), |
+| | return the number of elements |
+| | that can be stored without |
+| | reallocation. |
++-------------------------------------------+-----------------------------------+
+| ``data()`` | For containers that support it |
+| | (``std::vector``, ``QList``), |
+| | return a buffer viewing the |
+| | memory. |
++-------------------------------------------+-----------------------------------+
+| ``constData()`` | For containers that support it |
+| | (``std::vector``, ``QList``), |
+| | return a read-only buffer viewing |
+| | the memory. |
++-------------------------------------------+-----------------------------------+
+
+
+.. note:: ``std::span``, being a non-owning container, is currently replaced by a
+ ``std::vector`` for argument passing. This means that an opaque container
+ wrapping a ``std::span`` obtained from a function will be converted
+ to a ``std::vector`` by sequence conversion when passed to a function
+ taking a ``std::span``.
+ Opaque containers wrapping a ``std::vector`` can be passed without conversion.
+ This is currently experimental and subject to change.
Following is an example on creating an opaque container named ``IntVector``
from `std::vector<int>`, and using it in Python.
@@ -76,7 +86,7 @@ from `std::vector<int>`, and using it in Python.
We will consider three separate use cases.
**Case 1** - When a Python list is passed to C++ function
-`TestOpaqueContainer.getVectorSum(const std::vector<int>&)` as an opaque container
+``TestOpaqueContainer.getVectorSum(const std::vector<int>&)`` as an opaque container
.. code-block:: c
@@ -89,7 +99,7 @@ We will consider three separate use cases.
}
};
-**Case 2** - When we have a C++ class named `TestOpaqueContainer` with a `std::vector<int>`
+**Case 2** - When we have a C++ class named ``TestOpaqueContainer`` with a ``std::vector<int>``
public variable
.. code-block:: c
@@ -101,7 +111,7 @@ public variable
};
-**Case 3** - When we have a C++ class named `TestOpaqueContainer` with a `std::vector<int>` as
+**Case 3** - When we have a C++ class named ``TestOpaqueContainer`` with a ``std::vector<int>`` as
private variable and the variable is returned by a reference through a getter.
.. code-block:: c
@@ -123,9 +133,9 @@ private variable and the variable is returned by a reference through a getter.
of these examples are rather to show the different possibilities with opaque containers in
Shiboken than the class design.
-In all the three cases, we want to use `intVector` in Python through an opaque-container. The
-first thing to do is to create the corresponding `<container-type />` attribute in the typesystem
-file, making Shiboken aware of the `IntVector`.
+In all the three cases, we want to use ``intVector`` in Python through an opaque-container. The
+first thing to do is to create the corresponding ``<container-type />`` attribute in the typesystem
+file, making Shiboken aware of the ``IntVector``.
.. code-block:: xml
@@ -147,17 +157,17 @@ For the rest of the steps, we consider the three cases separately.
**Case 1** - When a Python list is passed to a C++ function
-As the next step, we create a typesystem entry for the class `TestOpaqueContainer`.
+As the next step, we create a typesystem entry for the class ``TestOpaqueContainer``.
.. code-block:: xml
<value-type name="TestOpaqueContainer" />
In this case, the typesystem entry is simple and the function
-`getVectorSum(const std::vector<int>&)` accepts `IntVector` as the parameter. This is
-because inherantly `IntVector` is the same as `std::vector<int>`.
+``getVectorSum(const std::vector<int>&)`` accepts ``IntVector`` as the parameter. This is
+because inherantly ``IntVector`` is the same as ``std::vector<int>``.
-Now, build the code to create the \*_wrapper.cpp and \*.so files which we import into Python.
+Now, build the code to create the ``*_wrapper.cpp`` and ``*.so`` files which we import into Python.
Verifying the usage in Python
@@ -173,7 +183,7 @@ Verifying the usage in Python
**Case 2** - When the variable is public
-We create a typesystem entry for the class `TestOpaqueContainer`.
+We create a typesystem entry for the class ``TestOpaqueContainer``.
.. code-block:: xml
@@ -181,11 +191,11 @@ We create a typesystem entry for the class `TestOpaqueContainer`.
<modify-field name="intVector" opaque-container="yes"/>
</value-type>
-In the `<modify-field />` notice the `opaque-container="yes"`. Since the type
-of `intVector' is `std::vector<int>`, it picks up the ``IntVector`` opaque
+In the ``<modify-field />`` notice the ``opaque-container="yes"``. Since the type
+of ``intVector`` is ``std::vector<int>``, it picks up the ``IntVector`` opaque
container.
-Build the code to create the \*_wrapper.cpp and \*.so files which we import into Python.
+Build the code to create the ``*_wrapper.cpp`` and ``*.so`` files which we import into Python.
Verifying the usage in Python
@@ -206,7 +216,7 @@ Verifying the usage in Python
**Case 3** - When the variable is private and returned by reference through a getter
-Similar to the previous cases, we create a typesystem entry for the class `TestOpaqueContainer`.
+Similar to the previous cases, we create a typesystem entry for the class ``TestOpaqueContainer``.
.. code-block:: xml
@@ -218,7 +228,7 @@ Similar to the previous cases, we create a typesystem entry for the class `TestO
</modify-function>
</value-type>
-In this case, we specify the name of the opaque container `IntVector` in the <replace-type />
+In this case, we specify the name of the opaque container ``IntVector`` in the ``<replace-type />``
field.
Build the code to create the \*_wrapper.cpp and \*.so files which we import into Python.
diff --git a/sources/shiboken6/doc/typesystem_conversionrule.rst b/sources/shiboken6/doc/typesystem_conversionrule.rst
index 4ac2bd365..9a8f51c18 100644
--- a/sources/shiboken6/doc/typesystem_conversionrule.rst
+++ b/sources/shiboken6/doc/typesystem_conversionrule.rst
@@ -8,99 +8,99 @@ Conversion Rule Tag
conversion-rule
^^^^^^^^^^^^^^^
- The **conversion-rule** tag specifies how a **primitive-type**, a **container-type**,
- or a **value-type** may be converted to and from the native C++ language types to the
- target language types (see also :ref:`user-defined-type-conversion`).
-
- It is a child of the :ref:`container-type`, :ref:`primitive-type` or
- :ref:`value-type` and may contain :ref:`native-to-target` or
- :ref:`native-to-target` child nodes.
-
- .. code-block:: xml
-
- <value-type>
- <conversion-rule>
- <native-to-target>
- // Code to convert a native value to a target language object.
- </native-to-target>
- <target-to-native>
- <add-conversion type='TARGETTYPEA' check='TARGETTYPEA_CHECK(%in)'>
- // Code to convert target language type object of type TARGETTYPEA
- // to the C++ native type represented by the value/primitive/container-type.
- </add-conversion>
- <add-conversion type='TARGETTYPEB' check='TARGETTYPEB_CHECK(%in)'>
- // Code to convert target language type object of type TARGETTYPEB
- // to the C++ native type represented by the value/primitive/container-type.
- </add-conversion>
- </target-to-native>
- </conversion-rule>
- </value-type>
-
- The code can be inserted directly, via :ref:`add-conversion` (providing snippet
- functionality) or via :ref:`insert-template` (XML template,
- see :ref:`using-code-templates`).
-
- The example above show the structure of a complete conversion rule. Each of the
- child tags comprising the conversion rule are described in their own sections
- below.
-
- .. note::
-
- You can also use the ``conversion-rule`` node to specify customized code
- to convert a function argument between the target language and C++
- (see :ref:`conversionrule-on-arguments`).
+The **conversion-rule** tag specifies how a **primitive-type**, a **container-type**,
+or a **value-type** may be converted to and from the native C++ language types to the
+target language types (see also :ref:`user-defined-type-conversion`).
-.. _native-to-target:
-
-native-to-target
-^^^^^^^^^^^^^^^^
-
- The **native-to-target** tag tells how to convert a native C++ value to its
- target language equivalent. It is a child of the :ref:`conversion-rule` node.
- The text inside the tag is a C++ code the takes
- an input value an does what's needed to convert it to the output value.
- :ref:`insert-template` tags may be used to insert commonly repeating code.
+It is a child of the :ref:`container-type`, :ref:`primitive-type` or
+:ref:`value-type` and may contain :ref:`native-to-target` or
+:ref:`native-to-target` child nodes.
- .. code-block:: xml
+.. code-block:: xml
+ <value-type>
<conversion-rule>
<native-to-target>
// Code to convert a native value to a target language object.
</native-to-target>
+ <target-to-native>
+ <add-conversion type='TARGETTYPEA' check='TARGETTYPEA_CHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPEA
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ <add-conversion type='TARGETTYPEB' check='TARGETTYPEB_CHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPEB
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ </target-to-native>
</conversion-rule>
+ </value-type>
- Use the replace node to modify the template code.
- Notice that the generator must provide type system variables for the input
- and output values and types, namely **%in**, **%out**, **%INTYPE** and
- **%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
- full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
- **%INTYPE_#**, should be replaced by the types used in the container template
- (e.g. **%INTYPE_0** correspondes to **"int"** for **"list<int>"**).
+The code can be inserted directly, via :ref:`add-conversion` (providing snippet
+functionality) or via :ref:`insert-template` (XML template,
+see :ref:`using-code-templates`).
- The ``file`` and ``snippet`` attributes are also supported (see :ref:`inject-code` nodes).
+The example above show the structure of a complete conversion rule. Each of the
+child tags comprising the conversion rule are described in their own sections
+below.
+
+.. note::
+
+ You can also use the ``conversion-rule`` node to specify customized code
+ to convert a function argument between the target language and C++
+ (see :ref:`conversionrule-on-arguments`).
+
+.. _native-to-target:
+
+native-to-target
+^^^^^^^^^^^^^^^^
+
+The **native-to-target** tag tells how to convert a native C++ value to its
+target language equivalent. It is a child of the :ref:`conversion-rule` node.
+The text inside the tag is a C++ code the takes
+an input value an does what's needed to convert it to the output value.
+:ref:`insert-template` tags may be used to insert commonly repeating code.
+
+.. code-block:: xml
+
+ <conversion-rule>
+ <native-to-target>
+ // Code to convert a native value to a target language object.
+ </native-to-target>
+ </conversion-rule>
+
+Use the replace node to modify the template code.
+Notice that the generator must provide type system variables for the input
+and output values and types, namely **%in**, **%out**, **%INTYPE** and
+**%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
+full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
+**%INTYPE_#**, should be replaced by the types used in the container template
+(e.g. **%INTYPE_0** correspondes to **"int"** for **"list<int>"**).
+
+The ``file`` and ``snippet`` attributes are also supported (see :ref:`inject-code` nodes).
.. _target-to-native:
target-to-native
^^^^^^^^^^^^^^^^
- The **target-to-native** tag encloses at least one, but usually many, conversions
- from target language values to C++ native values. It is a child of the
- :ref:`conversion-rule` node and may have one or several :ref:`add-conversion`
- child nodes. The *optional* attribute ``replace`` tells if the target
- language to C++ conversions will be added to, or if they will replace the
- implicit conversions collected by *ApiExtractor*. The default
- value for it is *yes*.
+The **target-to-native** tag encloses at least one, but usually many, conversions
+from target language values to C++ native values. It is a child of the
+:ref:`conversion-rule` node and may have one or several :ref:`add-conversion`
+child nodes. The *optional* attribute ``replace`` tells if the target
+language to C++ conversions will be added to, or if they will replace the
+implicit conversions collected by *ApiExtractor*. The default
+value for it is *yes*.
- .. code-block:: xml
+.. code-block:: xml
- <conversion-rule>
- <target-to-native replace='yes|no'>\
- // List of target to native conversions meant to replace or expand
- // the already existing implicit conversions.
- </target-to-native>
- </conversion-rule>
+ <conversion-rule>
+ <target-to-native replace='yes|no'>
+ // List of target to native conversions meant to replace or expand
+ // the already existing implicit conversions.
+ </target-to-native>
+ </conversion-rule>
.. _add-conversion:
@@ -108,26 +108,26 @@ target-to-native
add-conversion
^^^^^^^^^^^^^^
- Each **add-conversion** tag adds a rule for conversion of a target language type,
- indicated by the ``type`` attribute, to the C++ native type represented by the
- **primitive-type**, a **container-type**, or **value-type**, to which the parent
- **conversion-rule** belongs.
- It is a child of the :ref:`target-to-native` node.
+Each **add-conversion** tag adds a rule for conversion of a target language type,
+indicated by the ``type`` attribute, to the C++ native type represented by the
+**primitive-type**, a **container-type**, or **value-type**, to which the parent
+**conversion-rule** belongs.
+It is a child of the :ref:`target-to-native` node.
- .. code-block:: xml
+.. code-block:: xml
- <target-to-native>
- <add-conversion type='TARGETTYPE' check='TARGETTYPECHECK(%in)'>
- // Code to convert target language type object of type TARGETTYPE_A
- // to the C++ native type represented by the value/primitive/container-type.
- </add-conversion>
- <target-to-native>
+ <target-to-native>
+ <add-conversion type='TARGETTYPE' check='TARGETTYPECHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPE_A
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ <target-to-native>
- The ``check`` attribute tells how a target value should be checked to see if it belongs to
- the type expected. This attribute is *optional*, for it can be derived from the ``type``
- attribute, but it isn't unusual that some special check is needed. The variables
- **%in**, **%out**, **%INTYPE**, **%INTYPE_#**, and **%OUTTYPE**, must be provided by
- the generator as in the ``native-to-target`` tag.
+The ``check`` attribute tells how a target value should be checked to see if it belongs to
+the type expected. This attribute is *optional*, for it can be derived from the ``type``
+attribute, but it isn't unusual that some special check is needed. The variables
+**%in**, **%out**, **%INTYPE**, **%INTYPE_#**, and **%OUTTYPE**, must be provided by
+the generator as in the ``native-to-target`` tag.
- The ``file`` and ``snippet`` attributes are also supported (see :ref:`inject-code` nodes).
+The ``file`` and ``snippet`` attributes are also supported (see :ref:`inject-code` nodes).
diff --git a/sources/shiboken6/doc/typesystem_converters.rst b/sources/shiboken6/doc/typesystem_converters.rst
index 02600e7b1..ab6fba930 100644
--- a/sources/shiboken6/doc/typesystem_converters.rst
+++ b/sources/shiboken6/doc/typesystem_converters.rst
@@ -12,51 +12,51 @@ numbers, has a Python equivalent in the "complex" type.) Such classes, instead
of getting a Python wrapper, normally have conversions rules, from Python to
C++ and vice-versa.
- .. code-block:: c++
+.. code-block:: c++
- // C++ class
- struct Complex {
- Complex(double real, double imag);
- double real() const;
- double imag() const;
- };
+ // C++ class
+ struct Complex {
+ Complex(double real, double imag);
+ double real() const;
+ double imag() const;
+ };
- // Converting from C++ to Python using the CPython API:
- PyObject* pyCpxObj = PyComplex_FromDoubles(complex.real(), complex.imag());
+ // Converting from C++ to Python using the CPython API:
+ PyObject* pyCpxObj = PyComplex_FromDoubles(complex.real(), complex.imag());
- // Converting from Python to C++:
- double real = PyComplex_RealAsDouble(pyCpxObj);
- double imag = PyComplex_ImagAsDouble(pyCpxObj);
- Complex cpx(real, imag);
+ // Converting from Python to C++:
+ double real = PyComplex_RealAsDouble(pyCpxObj);
+ double imag = PyComplex_ImagAsDouble(pyCpxObj);
+ Complex cpx(real, imag);
For the user defined conversion code to be inserted in the proper places,
the :ref:`conversion-rule` tag must be used.
- .. code-block:: xml
+.. code-block:: xml
- <primitive-type name="Complex" target-lang-api-name="PyComplex">
- <include file-name="complex.h" location="global"/>
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
- <conversion-rule>
+ <conversion-rule>
- <native-to-target>
- return PyComplex_FromDoubles(%in.real(), %in.imag());
- </native-to-target>
+ <native-to-target>
+ return PyComplex_FromDoubles(%in.real(), %in.imag());
+ </native-to-target>
- <target-to-native>
- <!-- The 'check' attribute can be derived from the 'type' attribute,
- it is defined here to test the CHECKTYPE type system variable. -->
- <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)">
- double real = PyComplex_RealAsDouble(%in);
- double imag = PyComplex_ImagAsDouble(%in);
- %out = %OUTTYPE(real, imag);
- </add-conversion>
- </target-to-native>
+ <target-to-native>
+ <!-- The 'check' attribute can be derived from the 'type' attribute,
+ it is defined here to test the CHECKTYPE type system variable. -->
+ <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)">
+ double real = PyComplex_RealAsDouble(%in);
+ double imag = PyComplex_ImagAsDouble(%in);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+ </target-to-native>
- </conversion-rule>
+ </conversion-rule>
- </primitive-type>
+ </primitive-type>
The details will be given later, but the gist of it are the tags
@@ -78,53 +78,53 @@ of numbers to be accepted by wrapped C++ functions with "Complex" arguments,
an :ref:`add-conversion <add-conversion>` tag and a custom check must be added.
Here's how to do it:
- .. code-block:: xml
+.. code-block:: xml
- <!-- Code injection at module level. -->
- <inject-code class="native" position="beginning">
- static bool Check2TupleOfNumbers(PyObject* pyIn) {
- if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2))
- return false;
- Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0));
- if (!PyNumber_Check(pyReal))
- return false;
- Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1));
- if (!PyNumber_Check(pyImag))
- return false;
- return true;
- }
- </inject-code>
+ <!-- Code injection at module level. -->
+ <inject-code class="native" position="beginning">
+ static bool Check2TupleOfNumbers(PyObject* pyIn) {
+ if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2))
+ return false;
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0));
+ if (!PyNumber_Check(pyReal))
+ return false;
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1));
+ if (!PyNumber_Check(pyImag))
+ return false;
+ return true;
+ }
+ </inject-code>
- <primitive-type name="Complex" target-lang-api-name="PyComplex">
- <include file-name="complex.h" location="global"/>
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
- <conversion-rule>
+ <conversion-rule>
- <native-to-target>
- return PyComplex_FromDoubles(%in.real(), %in.imag());
- </native-to-target>
+ <native-to-target>
+ return PyComplex_FromDoubles(%in.real(), %in.imag());
+ </native-to-target>
- <target-to-native>
+ <target-to-native>
- <add-conversion type="PyComplex">
- double real = PyComplex_RealAsDouble(%in);
- double imag = PyComplex_ImagAsDouble(%in);
- %out = %OUTTYPE(real, imag);
- </add-conversion>
+ <add-conversion type="PyComplex">
+ double real = PyComplex_RealAsDouble(%in);
+ double imag = PyComplex_ImagAsDouble(%in);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
- <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)">
- Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0));
- Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1));
- double real = %CONVERTTOCPP[double](pyReal);
- double imag = %CONVERTTOCPP[double](pyImag);
- %out = %OUTTYPE(real, imag);
- </add-conversion>
+ <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)">
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0));
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1));
+ double real = %CONVERTTOCPP[double](pyReal);
+ double imag = %CONVERTTOCPP[double](pyImag);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
- </target-to-native>
+ </target-to-native>
- </conversion-rule>
+ </conversion-rule>
- </primitive-type>
+ </primitive-type>
.. _container_conversions:
@@ -138,48 +138,48 @@ except that they make use of the type system variables
|project| combines the conversion code for containers with the conversion
defined (or automatically generated) for the containers.
- .. code-block:: xml
-
- <container-type name="std::map" type="map">
- <include file-name="map" location="global"/>
-
- <conversion-rule>
-
- <native-to-target>
- PyObject* %out = PyDict_New();
- %INTYPE::const_iterator it = %in.begin();
- for (; it != %in.end(); ++it) {
- %INTYPE_0 key = it->first;
- %INTYPE_1 value = it->second;
- PyDict_SetItem(%out,
- %CONVERTTOPYTHON[%INTYPE_0](key),
- %CONVERTTOPYTHON[%INTYPE_1](value));
- }
- return %out;
- </native-to-target>
-
- <target-to-native>
-
- <add-conversion type="PyDict">
- PyObject* key;
- PyObject* value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
- %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
- %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
- %out.insert(%OUTTYPE::value_type(cppKey, cppValue));
- }
- </add-conversion>
-
- </target-to-native>
- </conversion-rule>
- </container-type>
-
-.. note:: From version 6.3, we do not have to explicitly specify the
- `<container-type/>` for C++ containers ``std::list``\, ``std::vector``\,
- ``std::pair``\, ``std::map`` and ``std::unordered_map``\. They are
- now built-in. However, they still have to be added for opaque
- containers or when modifying the built-in behavior.
+.. code-block:: xml
+
+ <container-type name="std::map" type="map">
+ <include file-name="map" location="global"/>
+
+ <conversion-rule>
+
+ <native-to-target>
+ PyObject* %out = PyDict_New();
+ %INTYPE::const_iterator it = %in.begin();
+ for (; it != %in.end(); ++it) {
+ %INTYPE_0 key = it->first;
+ %INTYPE_1 value = it->second;
+ PyDict_SetItem(%out,
+ %CONVERTTOPYTHON[%INTYPE_0](key),
+ %CONVERTTOPYTHON[%INTYPE_1](value));
+ }
+ return %out;
+ </native-to-target>
+
+ <target-to-native>
+
+ <add-conversion type="PyDict">
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
+ %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
+ %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
+ %out.insert(%OUTTYPE::value_type(cppKey, cppValue));
+ }
+ </add-conversion>
+
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+
+.. note:: The C++ containers ``std::list``\, ``std::vector``\,
+ ``std::pair``\, ``std::map``\, ``std::span`` and ``std::unordered_map`` are
+ built-in.
+ To specify :ref:`opaque-containers`, use the :ref:`opaque-container` element.
+ :ref:`container-type` can still be specified to modify the built-in behavior.
For this case, a number of pre-defined conversion templates
are provided (see :ref:`predefined_templates`).
@@ -192,14 +192,12 @@ Variables & Functions
.. _in:
**%in**
-
Variable replaced by the C++ input variable.
.. _out:
**%out**
-
Variable replaced by the C++ output variable. Needed to convey the
result of a Python to C++ conversion.
@@ -207,7 +205,6 @@ Variables & Functions
.. _intype:
**%INTYPE**
-
Used in Python to C++ conversions. It is replaced by the name of type for
which the conversion is being defined. Don't use the type's name directly.
@@ -215,14 +212,12 @@ Variables & Functions
.. _intype_n:
**%INTYPE_#**
-
Replaced by the name of the #th type used in a container.
.. _outtype:
**%OUTTYPE**
-
Used in Python to C++ conversions. It is replaced by the name of type for
which the conversion is being defined. Don't use the type's name directly.
@@ -230,71 +225,11 @@ Variables & Functions
.. _outtype_n:
**%OUTTYPE_#**
-
Replaced by the name of the #th type used in a container.
.. _checktype:
**%CHECKTYPE[CPPTYPE]**
-
Replaced by a |project| type checking function for a Python variable.
The C++ type is indicated by ``CPPTYPE``.
-
-
-.. _oldconverters:
-
-Converting The Old Converters
-=============================
-
-If you use |project| for your bindings, and has defined some type conversions
-using the ``Shiboken::Converter`` template, then you must update your converters
-to the new scheme.
-
-Previously your conversion rules were declared in one line, like this:
-
-
- .. code-block:: xml
-
- <primitive-type name="Complex" target-lang-api-name="PyComplex">
- <include file-name="complex.h" location="global"/>
- <conversion-rule file="complex_conversions.h"/>
- </primitive-type>
-
-
-And implemented in a separate C++ file, like this:
-
-
- .. code-block:: c++
-
- namespace Shiboken {
- template<> struct Converter<Complex>
- {
- static inline bool checkType(PyObject* pyObj) {
- return PyComplex_Check(pyObj);
- }
- static inline bool isConvertible(PyObject* pyObj) {
- return PyComplex_Check(pyObj);
- }
- static inline PyObject* toPython(void* cppobj) {
- return toPython(*reinterpret_cast<Complex*>(cppobj));
- }
- static inline PyObject* toPython(const Complex& cpx) {
- return PyComplex_FromDoubles(cpx.real(), cpx.imag());
- }
- static inline Complex toCpp(PyObject* pyobj) {
- double real = PyComplex_RealAsDouble(pyobj);
- double imag = PyComplex_ImagAsDouble(pyobj);
- return Complex(real, imag);
- }
- };
- }
-
-
-In this case, the parts of the implementation that will be used in the new
-conversion-rule are the ones in the two last method
-``static inline PyObject* toPython(const Complex& cpx)`` and
-``static inline Complex toCpp(PyObject* pyobj)``. The ``isConvertible`` method
-is gone, and the ``checkType`` is now an attribute of the :ref:`add-conversion <add-conversion>`
-tag. Refer back to the first example in this page and you will be able to
-correlate the above template with the new scheme of conversion rule definition.
diff --git a/sources/shiboken6/doc/typesystem_documentation.rst b/sources/shiboken6/doc/typesystem_documentation.rst
index f03d8b70a..4e7d18b99 100644
--- a/sources/shiboken6/doc/typesystem_documentation.rst
+++ b/sources/shiboken6/doc/typesystem_documentation.rst
@@ -4,48 +4,59 @@ Manipulating Documentation
inject-documentation
^^^^^^^^^^^^^^^^^^^^
- The inject-documentation node inserts the documentation into the generated
- documentation. This node is a child of the :ref:`object-type`,
- :ref:`value-type` and :ref:`modify-function` nodes.
+The inject-documentation node inserts the documentation into the generated
+documentation. This node is a child of the :ref:`object-type`,
+:ref:`value-type` and :ref:`modify-function` nodes.
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <inject-documentation mode="append | prepend | replace" format="native | target" >
- // the documentation
- </inject-code>
- </value-type>
+ <value-type>
+ <inject-documentation mode="append | prepend | replace" format="native | target"
+ file="[file]" snippet="[label]">
+ // the documentation
+ </inject-code>
+ </value-type>
- The **mode** attribute default value is *replace*.
+The **mode** attribute default value is *replace*.
- The **format** attribute specifies when the documentation injection will
- occur and it accepts the following values:
+The **format** attribute specifies when the documentation injection will
+occur and it accepts the following values:
- * native: Before XML<->Backend transformation occur, so the injected code *must* be a valid XML.
- * target: After XML<->Backend transformation occur, so the injected code *must* be a valid backend format.
+* native: Before XML<->Backend transformation occur, so the injected code *must* be a valid XML.
+* target: After XML<->Backend transformation occur, so the injected code *must* be a valid backend format.
- At the moment the only supported backend is Sphinx.
+The optional ``file`` attribute specifies the file name
+(see :ref:`external-snippets`).
+
+The optional ``snippet`` attribute specifies the snippet label
+(see :ref:`external-snippets`).
+
+At the moment the only supported backend is Sphinx.
+
+If the injected documentation contains a Sphinx function directive, no
+directive will be auto-generated. This can be used to add parameter
+documentation to added functions.
modify-documentation
^^^^^^^^^^^^^^^^^^^^
- The modify-documentation node allows you to change the auto-generated
- documentation. . This node is a child of the :ref:`object-type`,
- :ref:`value-type` and :ref:`modify-function` nodes.
- API Extractor transforms XML's from `qdoc`_ (the Qt documentation
- tool) into .rst files to be processed later using `Sphinx`_. You can modify
- the XML before the transformation takes place.
+The modify-documentation node allows you to change the auto-generated
+documentation. . This node is a child of the :ref:`object-type`,
+:ref:`value-type` and :ref:`modify-function` nodes.
+API Extractor transforms XML's from `qdoc`_ (the Qt documentation
+tool) into .rst files to be processed later using `Sphinx`_. You can modify
+the XML before the transformation takes place.
.. _`qdoc`: https://doc.qt.io/qt-6/qdoc-index.html
.. _`Sphinx`: https://www.sphinx-doc.org/en/master
- .. code-block:: xml
+.. code-block:: xml
- <modify-documentation xpath="...">
- <!-- new documentation -->
- </modify-documentation>
+ <modify-documentation xpath="...">
+ <!-- new documentation -->
+ </modify-documentation>
- The **xpath** attribute is the `XPath`_ to the node that you want to modify.
+The **xpath** attribute is the `XPath`_ to the node that you want to modify.
.. _`XPath`: https://www.w3.org/TR/1999/REC-xpath-19991116/
diff --git a/sources/shiboken6/doc/typesystem_manipulating_objects.rst b/sources/shiboken6/doc/typesystem_manipulating_objects.rst
index 88aa18390..e024cdf00 100644
--- a/sources/shiboken6/doc/typesystem_manipulating_objects.rst
+++ b/sources/shiboken6/doc/typesystem_manipulating_objects.rst
@@ -8,75 +8,75 @@ Manipulating Object and Value Types
inject-code
^^^^^^^^^^^
- The ``inject-code`` node inserts the given code into the generated code for the
- given type or function, and it is a child of the :ref:`object-type`, :ref:`value-type`,
- :ref:`modify-function` and :ref:`add-function` nodes.
- It may contain :ref:`insert-template` child nodes.
+The ``inject-code`` node inserts the given code into the generated code for the
+given type or function, and it is a child of the :ref:`object-type`, :ref:`value-type`,
+:ref:`modify-function` and :ref:`add-function` nodes.
+It may contain :ref:`insert-template` child nodes.
- .. code-block:: xml
+.. code-block:: xml
- <inject-code class="native | target"
- position="beginning | end" since="..."
- file="[file]"
- snippet="[label]"/>
+ <inject-code class="native | target"
+ position="beginning | end" since="..."
+ file="[file]"
+ snippet="[label]"/>
- The ``class`` attribute specifies which module of the generated code that
- will be affected by the code injection
- (see :ref:`codegenerationterminology`). The ``class`` attribute accepts the
- following values:
+The ``class`` attribute specifies which module of the generated code that
+will be affected by the code injection
+(see :ref:`codegenerationterminology`). The ``class`` attribute accepts the
+following values:
- * ``native``: The c++ code
- * ``target``: The binding code
+* ``native``: The c++ code
+* ``target``: The binding code
- If the ``position`` attribute is set to *beginning* (the default), the code
- is inserted at the beginning of the function. If it is set to *end*, the code
- is inserted at the end of the function.
+If the ``position`` attribute is set to *beginning* (the default), the code
+is inserted at the beginning of the function. If it is set to *end*, the code
+is inserted at the end of the function.
- For a detailed description of how to above attributes interact,
- see :ref:`codeinjectionsemantics`.
+For a detailed description of how to above attributes interact,
+see :ref:`codeinjectionsemantics`.
- The optional ``file`` attribute specifies the file name
- (see :ref:`external-snippets`).
+The optional ``file`` attribute specifies the file name
+(see :ref:`external-snippets`).
- The optional ``snippet`` attribute specifies the snippet label
- (see :ref:`external-snippets`).
+The optional ``snippet`` attribute specifies the snippet label
+(see :ref:`external-snippets`).
- There are a number of placeholders which are replaced when injecting
- code (see :ref:`typesystemvariables`).
+There are a number of placeholders which are replaced when injecting
+code (see :ref:`typesystemvariables`).
- There are severals ways to specify the code:
+There are severals ways to specify the code:
Embedding Code into XML
=======================
- The code can be embedded into XML (be careful to use the correct XML entities
- for characters like '<', '>', '&'):
+The code can be embedded into XML (be careful to use the correct XML entities
+for characters like '<', '>', '&'):
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <inject-code class="native | target"
- position="beginning | end" since="...">
- // the code
- </inject-code>
- </value-type>
+ <value-type>
+ <inject-code class="native | target"
+ position="beginning | end" since="...">
+ // the code
+ </inject-code>
+ </value-type>
Using a Template Specified in XML
=================================
- It is possible to create code templates for reuse in XML
- (see :ref:`using-code-templates`). This allows for replacing of custom
- placeholders.
+It is possible to create code templates for reuse in XML
+(see :ref:`using-code-templates`). This allows for replacing of custom
+placeholders.
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <inject-code class="native | target" class="native | target">
- <insert-template name="template_name"/>
- </inject-code>
- </value-type>
+ <value-type>
+ <inject-code class="native | target" class="native | target">
+ <insert-template name="template_name"/>
+ </inject-code>
+ </value-type>
.. _external-snippets:
@@ -84,267 +84,291 @@ Using a Template Specified in XML
Using Snippets From External Files
==================================
- Code snippets can also be retrieved from external files found in the
- typesystem search path (see :ref:`typesystem-paths`).
+Code or documentation snippets can also be retrieved from external
+files found in the typesystem search path (see :ref:`typesystem-paths`).
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <inject-code class="native | target"
- position="beginning | end" since="..."
- file="external_source.cpp"
- snippet="label"/>
- </value-type>
+ <value-type>
+ <inject-code class="native | target"
+ position="beginning | end" since="..."
+ file="external_source.cpp"
+ snippet="label"/>
+ </value-type>
- In the external file ``external_source.cpp``, the code between annotations
- of the form:
+In the external file ``external_source.cpp``, the code between annotations
+of the form:
- .. code-block:: c++
+.. code-block:: c++
- // @snippet label
- ...
- // @snippet label
+ // @snippet label
+ ...
+ // @snippet label
- will be extracted.
+will be extracted.
.. _modify-field:
modify-field
^^^^^^^^^^^^
- The ``modify-field`` node allows you to alter the access privileges for a given
- C++ field when mapping it onto the target language, and it is a child of an
- :ref:`object-type` or a :ref:`value-type` node.
+The ``modify-field`` node allows you to alter the access privileges for a given
+C++ field when mapping it onto the target language, and it is a child of an
+:ref:`object-type` or a :ref:`value-type` node.
- .. code-block:: xml
+.. code-block:: xml
- <object-type>
- <modify-field name="..."
- write="true | false"
- read="true | false"
- remove="true | false"
- opaque-container = "yes | no"
- snake-case="yes | no | both" />
- </object-type>
+ <object-type>
+ <modify-field name="..."
+ write="true | false"
+ read="true | false"
+ remove="true | false"
+ opaque-container = "yes | no"
+ snake-case="yes | no | both" />
+ </object-type>
- The ``name`` attribute is the name of the field, the *optional* ``write``
- and ``read`` attributes specify the field's access privileges in the target
- language API (both are set to true by default).
+The ``name`` attribute is the name of the field, the *optional* ``write``
+and ``read`` attributes specify the field's access privileges in the target
+language API (both are set to true by default).
- The ``remove`` attribute is an *optional* boolean attribute, which can
- mark the field to be discarded on generation.
+The ``remove`` attribute is an *optional* boolean attribute, which can
+mark the field to be discarded on generation.
- The *optional* ``rename`` attribute can be used to change the name of the
- given field in the generated target language API.
+The *optional* ``rename`` attribute can be used to change the name of the
+given field in the generated target language API.
- The *optional* ``opaque-container`` attribute specifies whether
- an opaque container should be returned on read access
- (see :ref:`opaque-containers`).
+The *optional* ``opaque-container`` attribute specifies whether
+an opaque container should be returned on read access
+(see :ref:`opaque-containers`).
- The *optional* **snake-case** attribute allows for overriding the value
- specified on the class entry or **typesystem** element.
+The *optional* **snake-case** attribute allows for overriding the value
+specified on the class entry or **typesystem** element.
.. _modify-function:
modify-function
^^^^^^^^^^^^^^^
- The ``modify-function`` node allows you to modify a given C++ function when
- mapping it onto the target language, and it is a child of a :ref:`function`,
- :ref:`namespace`, :ref:`object-type` or a :ref:`value-type` node.
- Use the :ref:`modify-argument` node to specify which argument the
- modification affects.
-
- .. code-block:: xml
-
- <object-type>
- <modify-function signature="..."
- since="..."
- remove="true | false"
- access="public | private | protected"
- allow-thread="true | auto | false"
- exception-handling="off | auto-off | auto-on | on"
- overload-number="number"
- rename="..."
- snake-case="yes | no | both" />
- </object-type>
-
- The ``signature`` attribute is a normalized C++ signature, excluding return
- values but including potential const declarations. It is not required
- when ``modify-function`` appears as a child of a :ref:`function` node to
- modify a global function.
-
- The ``since`` attribute specify the API version when this function was modified.
-
- The ``allow-thread`` attribute specifies whether a function should be wrapped
- into ``Py_BEGIN_ALLOW_THREADS`` and ``Py_END_ALLOW_THREADS``, that is,
- temporarily release the GIL (global interpreter lock). Doing so is required
- for any thread-related function (wait operations), functions that might call
- a virtual function (potentially reimplemented in Python), and recommended for
- lengthy I/O operations or similar. It has performance costs, though.
- The value ``auto`` means that it will be turned off for functions for which
- it is deemed to be safe, for example, simple getters.
- The attribute defaults to ``false``.
-
- The ``exception-handling`` attribute specifies whether to generate exception
- handling code (nest the function call into try / catch statements). It accepts
- the following values:
-
- * no, false: Do not generate exception handling code
- * auto-off: Generate exception handling code for functions
- declaring a non-empty ``throw`` list
- * auto-on: Generate exception handling code unless function
- declares ``noexcept``
- * yes, true: Always generate exception handling code
-
- The optional ``overload-number`` attribute specifies the position of the
- overload when checking arguments. Typically, when a number of overloads
- exists, as for in example in Qt:
-
- .. code-block:: c++
-
- void QPainter::drawLine(QPointF, QPointF);
- void QPainter::drawLine(QPoint, QPoint);
-
- they will be reordered such that the check for matching arguments for the
- one taking a ``QPoint`` is done first. This is to avoid a potentially
- costly implicit conversion from ``QPoint`` to ``QPointF`` when using the
- 2nd overload. There are cases though in which this is not desired;
- most prominently when a class inherits from a container and overloads exist
- for both types as is the case for the ``QPolygon`` class:
-
- .. code-block:: c++
-
- class QPolygon : public QList<QPoint> {};
-
- void QPainter::drawPolygon(QPolygon);
- void QPainter::drawPolygon(QList<QPoint>);
-
- By default, the overload taking a ``QList`` will be checked first, trying
- to avoid constructing a ``QPolygon`` from ``QList``. The type check for a
- list of points will succeed for a parameter of type ``QPolygon``, too,
- since it inherits ``QList``. This presents a problem since the sequence
- type check is costly due to it checking that each container element is a
- ``QPoint``. It is thus preferable to check for the ``QPolygon`` overload
- first. This is achieved by specifying numbers as follows:
-
- .. code-block:: xml
-
- <object-type name="QPainter">
- <modify-function signature="drawPolygon(QPolygon)" overload-number="0"/>
- <modify-function signature="drawPolygon(QList&lt;QPoint&gt;)" overload-number="1"/>
- </object-type>
-
- Numbers should be given for all overloads; otherwise, the order will be in
- declaration order.
-
- The ``remove`` attribute is an *optional* boolean attribute, which can
- mark the function to be discarded on generation.
-
- The *optional* ``rename`` attribute can be used to change the name of the
- given function in the generated target language API.
-
- The *optional* ``access`` attribute changes the access privileges of the
- given function in the generated target language API.
-
- The *optional* **snake-case** attribute allows for overriding the value
- specified on the class entry or **typesystem** element.
+The ``modify-function`` node allows you to modify a given C++ function when
+mapping it onto the target language, and it is a child of a :ref:`function`,
+:ref:`namespace`, :ref:`object-type` or a :ref:`value-type` node.
+Use the :ref:`modify-argument` node to specify which argument the
+modification affects.
+
+.. code-block:: xml
+
+ <object-type>
+ <modify-function signature="..."
+ since="..."
+ remove="true | false"
+ access="public | private | protected"
+ allow-thread="true | auto | false"
+ exception-handling="no | auto-off | auto-on | yes"
+ final="true | false"
+ overload-number="number"
+ rename="..."
+ snake-case="yes | no | both"
+ deprecated = "true | false" />
+ </object-type>
+
+The ``signature`` attribute is a normalized C++ signature, excluding return
+values but including potential const declarations. It is not required
+when ``modify-function`` appears as a child of a :ref:`function` node to
+modify a global function.
+
+The ``since`` attribute specify the API version when this function was modified.
+
+The ``allow-thread`` attribute specifies whether a function should be wrapped
+into ``Py_BEGIN_ALLOW_THREADS`` and ``Py_END_ALLOW_THREADS``, that is,
+temporarily release the GIL (global interpreter lock). Doing so is required
+for any thread-related function (wait operations), functions that might call
+a virtual function (potentially reimplemented in Python), and recommended for
+lengthy I/O operations or similar. It has performance costs, though.
+The value ``auto`` means that it will be turned off for functions for which
+it is deemed to be safe, for example, simple getters.
+The attribute defaults to ``false``.
+
+The ``exception-handling`` attribute specifies whether to generate exception
+handling code (nest the function call into try / catch statements). It accepts
+the following values:
+
+* no, false: Do not generate exception handling code
+* auto-off: Generate exception handling code for functions
+ declaring a non-empty ``throw`` list
+* auto-on: Generate exception handling code unless function
+ declares ``noexcept``
+* yes, true: Always generate exception handling code
+
+The optional ``overload-number`` attribute specifies the position of the
+overload when checking arguments. Typically, when a number of overloads
+exists, as for in example in Qt:
+
+.. code-block:: c++
+
+ void QPainter::drawLine(QPointF, QPointF);
+ void QPainter::drawLine(QPoint, QPoint);
+
+they will be reordered such that the check for matching arguments for the
+one taking a ``QPoint`` is done first. This is to avoid a potentially
+costly implicit conversion from ``QPoint`` to ``QPointF`` when using the
+2nd overload. There are cases though in which this is not desired;
+most prominently when a class inherits from a container and overloads exist
+for both types as is the case for the ``QPolygon`` class:
+
+.. code-block:: c++
+
+ class QPolygon : public QList<QPoint> {};
+
+ void QPainter::drawPolygon(QPolygon);
+ void QPainter::drawPolygon(QList<QPoint>);
+
+By default, the overload taking a ``QList`` will be checked first, trying
+to avoid constructing a ``QPolygon`` from ``QList``. The type check for a
+list of points will succeed for a parameter of type ``QPolygon``, too,
+since it inherits ``QList``. This presents a problem since the sequence
+type check is costly due to it checking that each container element is a
+``QPoint``. It is thus preferable to check for the ``QPolygon`` overload
+first. This is achieved by specifying numbers as follows:
+
+.. code-block:: xml
+
+ <object-type name="QPainter">
+ <modify-function signature="drawPolygon(QPolygon)" overload-number="0"/>
+ <modify-function signature="drawPolygon(QList&lt;QPoint&gt;)" overload-number="1"/>
+ </object-type>
+
+Numbers should be given for all overloads; otherwise, the order will be in
+declaration order.
+
+The optional ``final`` attribute can be specified for virtual functions
+and disables generating the code for overriding the function in Python
+(native call). This is useful when the result type is not constructible.
+
+The ``remove`` attribute is an *optional* boolean attribute, which can
+mark the function to be discarded on generation.
+
+The *optional* ``rename`` attribute can be used to change the name of the
+given function in the generated target language API.
+
+The *optional* ``access`` attribute changes the access privileges of the
+given function in the generated target language API.
+
+The *optional* **snake-case** attribute allows for overriding the value
+specified on the class entry or **typesystem** element.
+
+The *optional* **deprecated** attribute allows for overriding deprecation
+as detected by the C++ attribute. It works in both ways.
.. _add-function:
add-function
^^^^^^^^^^^^
- The ``add-function`` node allows you to add a given function onto the target
- language, and it is a child of an :ref:`object-type` or :ref:`value-type` nodes if the
- function is supposed to be a method, or :ref:`namespace` and :ref:`typesystem` if
- the function is supposed to be a function inside a namespace or a global function.
- It may contain :ref:`modify-argument` nodes.
+The ``add-function`` node allows you to add a given function onto the target
+language, and it is a child of an :ref:`object-type` or :ref:`value-type` nodes if the
+function is supposed to be a method, or :ref:`namespace` and :ref:`typesystem` if
+the function is supposed to be a function inside a namespace or a global function.
+It may contain :ref:`modify-argument` nodes.
- Typically when adding a function some code must be injected to provide the function
- logic. This can be done using the :ref:`inject-code` node.
+Typically when adding a function some code must be injected to provide the function
+logic. This can be done using the :ref:`inject-code` node.
- .. code-block:: xml
+.. code-block:: xml
- <object-type>
- <add-function signature="..." return-type="..."
- access="public | protected"
- static="yes | no" classmethod="yes | no"
- since="..."/>
- </object-type>
+ <object-type>
+ <add-function signature="..." return-type="..."
+ access="public | protected"
+ overload-number="number"
+ static="yes | no" classmethod="yes | no"
+ python-override ="yes | no"
+ since="..."/>
+ </object-type>
- The ``return-type`` attribute defaults to *void*, the ``access`` to *public* and the ``static`` one to *no*.
+The ``return-type`` attribute defaults to *void*, the ``access`` to *public* and the ``static`` one to *no*.
- The ``since`` attribute specifies the API version when this function was added.
+The ``since`` attribute specifies the API version when this function was added.
- The ``classmethod`` attribute specifies whether the function should be a Python class method.
- It sets the METH_CLASS flag which means that ``PyTypeObject`` instead of an instance
- ``PyObject`` is passed as self, which needs to be handled in injected code.
+The ``classmethod`` attribute specifies whether the function should be a Python class method.
+It sets the METH_CLASS flag which means that ``PyTypeObject`` instead of an instance
+``PyObject`` is passed as self, which needs to be handled in injected code.
- Note that the label "static" in Qt's class documentation almost always means that a Python
- ``classmethod`` should be generated, because an object's class is always accessible from the
- static C++ code, while Python needs the explicit "self" parameter that ``classmethod``
- provides.
+For the *optional* attribute ``overload-number``, see :ref:`modify-function`.
- In order to create keyword argument supporting function parameters, enclose the specific
- function parameter with a *@* in the `signature` field.
+Note that the label "static" in Qt's class documentation almost always means that a Python
+``classmethod`` should be generated, because an object's class is always accessible from the
+static C++ code, while Python needs the explicit "self" parameter that ``classmethod``
+provides.
- .. code-block:: xml
+In order to create keyword argument supporting function parameters, enclose the specific
+function parameter with a *@* in the `signature` field.
- <add-function signature="foo(int @parameter1@,float @parameter2@)">
- ...
- </add-function>
+.. code-block:: xml
- With keyword arguments, ``add-function`` makes it easy to specify a default argument
- within the `signature` field
+ <add-function signature="foo(int @parameter1@,float @parameter2@)">
+ ...
+ </add-function>
- .. code-block:: xml
+With keyword arguments, ``add-function`` makes it easy to specify a default argument
+within the `signature` field
- <add-function signature="foo(int @parameter1@=1,float @parameter2@=2)">
- ...
- </add-function>
+.. code-block:: xml
+
+ <add-function signature="foo(int @parameter1@=1,float @parameter2@=2)">
+ ...
+ </add-function>
+
+See :ref:`sequence-protocol` for adding the respective functions.
- See :ref:`sequence-protocol` for adding the respective functions.
+The *optional* attribute ``python-override`` indicates a special type
+of added function, a python-override that will be generated into
+the native wrapper (see :ref:`modifying-virtual-functions`).
.. _declare-function:
declare-function
^^^^^^^^^^^^^^^^
- The ``declare-function`` node allows you to declare a function present in
- the type and it is a child of an :ref:`object-type` or :ref:`value-type` nodes
- if the function is supposed to be a method, or :ref:`namespace` and
- :ref:`typesystem` if the function is supposed to be a function inside a
- namespace or a global function. It may contain :ref:`modify-argument` nodes.
+The ``declare-function`` node allows you to declare a function present in
+the type and it is a child of an :ref:`object-type` or :ref:`value-type` nodes
+if the function is supposed to be a method, or :ref:`namespace` and
+:ref:`typesystem` if the function is supposed to be a function inside a
+namespace or a global function. It may contain :ref:`modify-argument` nodes.
- .. code-block:: xml
+.. code-block:: xml
+
+ <container-type>
+ <declare-function signature="..." return-type="..." since="..."
+ allow-thread="true | auto | false"
+ exception-handling="off | auto-off | auto-on | on"
+ overload-number="number"
+ snake-case="yes | no | both"/>
+ </container-type>
- <container-type>
- <declare-function signature="..." return-type="..." since="..."/>
- </container-type>
+The ``return-type`` attribute defaults to *void*.
- The ``return-type`` attribute defaults to *void*.
+The ``since`` attribute specifies the API version when this function was
+added.
- The ``since`` attribute specifies the API version when this function was
- added.
+For the *optional* attributes ``allow-thread``, ``exception-handling``,
+``overload-number`` and ``snake-case``, see :ref:`modify-function`.
- This is useful to make functions known to shiboken which its code parser
- does not detect. For example, in Qt 6, the ``append()`` function of the
- ``QList<T>`` container takes an argument of ``parameter_type`` which is
- specialized to ``T`` for simple types and ``const T &`` for complex types
- by some template expression which the code parser cannot resolve.
- In that case, the function can be declared with a simple signature:
+This is useful to make functions known to shiboken which its code parser
+does not detect. For example, in Qt 6, the ``append()`` function of the
+``QList<T>`` container takes an argument of ``parameter_type`` which is
+specialized to ``T`` for simple types and ``const T &`` for complex types
+by some template expression which the code parser cannot resolve.
+In that case, the function can be declared with a simple signature:
- .. code-block:: xml
+.. code-block:: xml
- <container-type name="QList">
- <declare-function signature="append(T)"/>
- </container-type>
+ <container-type name="QList">
+ <declare-function signature="append(T)"/>
+ </container-type>
- This tells shiboken a public function of that signature exists and
- bindings will be created in specializations of ``QList``.
+This tells shiboken a public function of that signature exists and
+bindings will be created in specializations of ``QList``.
.. _add-pymethoddef:
@@ -383,75 +407,150 @@ of signatures of the function.
property
^^^^^^^^
- The ``property`` element allows you to specify properties consisting of
- a type and getter and setter functions.
+The ``property`` element allows you to specify properties consisting of
+a type and getter and setter functions.
- It may appear as a child of a complex type such as :ref:`object-type` or
- :ref:`value-type`.
+It may appear as a child of a complex type such as :ref:`object-type` or
+:ref:`value-type`.
- If the PySide6 extension is not present, code will be generated using the
- ``PyGetSetDef`` struct, similar to what is generated for fields.
+If the PySide6 extension is not present, code will be generated using the
+``PyGetSetDef`` struct, similar to what is generated for fields.
- If the PySide6 extension is present, those properties complement the
- properties obtained from the ``Q_PROPERTY`` macro in Qt-based code.
- The properties will be handled in ``libpyside`` unless code generation
- is forced.
+If the PySide6 extension is present, those properties complement the
+properties obtained from the ``Q_PROPERTY`` macro in Qt-based code.
+The properties will be handled in ``libpyside`` unless code generation
+is forced.
- .. code-block:: xml
+.. code-block:: xml
+
+ <property name="..." type="..." get="..." set="..."
+ generate-getsetdef="yes | no" since="..."/>
+
+The ``name`` attribute specifies the name of the property, the ``type``
+attribute specifies the C++ type and the ``get`` attribute specifies the
+name of the accessor function.
+
+The optional ``set`` attribute specifies name of the setter function.
+
+The optional ``generate-getsetdef`` attribute specifies whether to generate
+code for if the PySide6 extension is present (indicating this property is not
+handled by libpyside). It defaults to *no*.
+
+The optional ``since`` attribute specifies the API version when this
+property appears.
+
+For a typical C++ class, like:
+
+.. code-block:: c++
+
+ class Test {
+ public:
+ int getValue() const;
+ void setValue();
+ };
+
+``value`` can then be specified to be a property:
+
+.. code-block:: xml
+
+ <value-type name="Test">
+ <property name="value" type="int" get="getValue" set="setValue"/>
+
+With that, a more pythonic style can be used:
+
+.. code-block:: python
- <property name="..." type="..." get="..." set="..."
- generate-getsetdef="yes | no" since="..."/>
+ test = Test()
+ test.value = 42
- The ``name`` attribute specifies the name of the property, the ``type``
- attribute specifies the C++ type and the ``get`` attribute specifies the
- name of the accessor function.
+For Qt classes (with the PySide6 extension present), additional setters
+and getters that do not appear as ``Q_PROPERTY``, can be specified to
+be properties:
- The optional ``set`` attribute specifies name of the setter function.
+.. code-block:: xml
+
+ <object-type name="QMainWindow">
+ <property name="centralWidget" type="QWidget *"
+ get="centralWidget" set="setCentralWidget"/>
+
+in addition to the normal properties of ``QMainWindow`` defined for
+Qt Designer usage.
+
+.. note:: In the *Qt* coding style, the property name typically conflicts
+ with the getter name. It is recommended to exclude the getter from the
+ wrapper generation using the ``remove`` function modification.
- The optional ``generate-getsetdef`` attribute specifies whether to generate
- code for if the PySide6 extension is present (indicating this property is not
- handled by libpyside). It defaults to *no*.
+.. _configuration-element:
- The optional ``since`` attribute specifies the API version when this
- property appears.
+configuration
+^^^^^^^^^^^^^
+
+The ``configuration`` element allows you to generate a preprocessor
+condition excluding a type depending on an expression into the module
+header. This is specifically tailored to the
+`Qt Feature system <https://doc.qt.io/qt-6/configure-options.html>`_ ,
+but may also be used for similar systems.
+
+It may appear as a child of a complex type such as :ref:`object-type` or
+:ref:`value-type`.
+
+.. code-block:: xml
- For a typical C++ class, like:
+ <configuration condition="..."/>
- .. code-block:: c++
+The ``condition`` attribute specifies the preprocessor condition.
- class Test {
- public:
- int getValue() const;
- void setValue();
- };
+This is an alternative way of omitting classes depending on some
+configuration (see also option :ref:`drop-type-entries`) intended
+for building several configurations from one generated source tree,
+but still requires listing the correct source files in the
+``CMakeLists.txt`` file.
- ``value`` can then be specified to be a property:
+.. _modifying-virtual-functions:
- .. code-block:: xml
+Modifying virtual functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
- <value-type name="Test">
- <property name="value" type="int" get="getValue" set="setValue"/>
+Some C++ virtual functions are unsuitable for Python bindings:
- With that, a more pythonic style can be used:
+.. code-block:: c
- .. code-block:: python
+ virtual void getInt(int *result) const;
- test = Test()
- test.value = 42
+In that case, you would modify it to return the integer instead (or a tuple
+in case of several out-parameters):
- For Qt classes (with the PySide6 extension present), additional setters
- and getters that do not appear as ``Q_PROPERTY``, can be specified to
- be properties:
+.. code-block:: c
- .. code-block:: xml
+ virtual int getInt() const;
- <object-type name="QMainWindow">
- <property name="centralWidget" type="QWidget *"
- get="centralWidget" set="setCentralWidget"/>
+For the binding itself, use the common argument modifications (removing
+arguments, modifying return types with injected code snippets) to modify the
+signature.
- in addition to the normal properties of ``QMainWindow`` defined for
- Qt Designer usage.
+To make it possible to reimplement the function in Python with the modified
+signature, add a ``python-override`` function with that signature, using an
+arbitrary name for disambiguation:
+
+.. code-block:: xml
+
+ <add-function signature="getIntPyOverride()"
+ return-type="int" python-override="true"/>
+
+This causes a static function performing the call into Python for the override
+to be generated into the native wrapper.
+
+In the existing virtual function, inject a code snippet at the ``shell`` /
+``override`` position which calls the newly added function. The first 2
+arguments are the `Global interpreter lock handle` (``Shiboken::GilState``) and
+the Python method determined by the override check (``PyObject *``). The
+snippet then converts the arguments and return values and returns after that:
+
+.. code-block:: xml
- .. note:: In the *Qt* coding style, the property name typically conflicts
- with the getter name. It is recommended to exclude the getter from the
- wrapper generation using the ``remove`` function modification.
+ <modify-function signature="getInt(int*)const">
+ <inject-code class="shell" position="override">
+ *result = getIntPyOverride(gil, pyOverride.object());
+ return;
+ </inject-code>
+ </modify-function>
diff --git a/sources/shiboken6/doc/typesystem_modify_function.rst b/sources/shiboken6/doc/typesystem_modify_function.rst
index 1e882f9c7..54ac6412f 100644
--- a/sources/shiboken6/doc/typesystem_modify_function.rst
+++ b/sources/shiboken6/doc/typesystem_modify_function.rst
@@ -8,37 +8,37 @@ Modifying Functions
modify-argument
^^^^^^^^^^^^^^^
- Function modifications consist of a list of ``modify-argument`` nodes
- contained in :ref:`modify-function`, :ref:`add-function` or
- :ref:`declare-function` nodes. Use the :ref:`remove-argument`,
- :ref:`replace-default-expression`, :ref:`remove-default-expression`,
- :ref:`replace-type`, :ref:`reference-count` and :ref:`define-ownership`
- nodes to specify the details of the modification.
-
- .. code-block:: xml
-
- <modify-function>
- <modify-argument index="return | this | 1 ..." rename="..."
- invalidate-after-use = "true | false" pyi-type="...">
- // modifications
- </modify-argument>
- </modify-function>
-
- Set the ``index`` attribute to "1" for the first argument, "2" for the second
- one and so on. Alternatively, set it to "return" or "this" if you want to
- modify the function's return value or the object the function is called upon,
- respectively.
-
- The optional ``rename`` attribute is used to rename a argument and use this
- new name in the generated code. This attribute can be used to enable the usage
- of ``keyword arguments``.
-
- The optional ``pyi-type`` attribute specifies the type to appear in the
- signature strings and ``.pyi`` files. The type string is determined by
- checking this attribute value, the :ref:`replace-type` modification and
- the C++ type. The attribute can be used for example to enclose
- a pointer return value within ``Optional[]`` to indicate that ``None``
- can occur.
-
- For the optional ``invalidate-after-use`` attribute,
- see :ref:`invalidationafteruse` .
+Function modifications consist of a list of ``modify-argument`` nodes
+contained in :ref:`modify-function`, :ref:`add-function` or
+:ref:`declare-function` nodes. Use the :ref:`remove-argument`,
+:ref:`replace-default-expression`, :ref:`remove-default-expression`,
+:ref:`replace-type`, :ref:`reference-count` and :ref:`define-ownership`
+nodes to specify the details of the modification.
+
+.. code-block:: xml
+
+ <modify-function>
+ <modify-argument index="return | this | 1 ..." rename="..."
+ invalidate-after-use = "true | false" pyi-type="...">
+ // modifications
+ </modify-argument>
+ </modify-function>
+
+Set the ``index`` attribute to "1" for the first argument, "2" for the second
+one and so on. Alternatively, set it to "return" or "this" if you want to
+modify the function's return value or the object the function is called upon,
+respectively.
+
+The optional ``rename`` attribute is used to rename a argument and use this
+new name in the generated code. This attribute can be used to enable the usage
+of ``keyword arguments``.
+
+The optional ``pyi-type`` attribute specifies the type to appear in the
+signature strings and ``.pyi`` files. The type string is determined by
+checking this attribute value, the :ref:`replace-type` modification and
+the C++ type. The attribute can be used for example to enclose
+a pointer return value within ``Optional[]`` to indicate that ``None``
+can occur.
+
+For the optional ``invalidate-after-use`` attribute,
+see :ref:`invalidationafteruse` .
diff --git a/sources/shiboken6/doc/typesystem_ownership.rst b/sources/shiboken6/doc/typesystem_ownership.rst
index f412fc609..a5440e49e 100644
--- a/sources/shiboken6/doc/typesystem_ownership.rst
+++ b/sources/shiboken6/doc/typesystem_ownership.rst
@@ -58,39 +58,39 @@ The following situations can invalidate an object:
C++ taking ownership
--------------------
- When an object is passed to a function or method that takes ownership of it, the wrapper
- is invalidated as we can't be sure of when the object is destroyed, unless it has a
- :ref:`virtual destructor <ownership-virt-method>` or the transfer is due to the special case
- of :ref:`parent ownership <ownership-parent>`.
+When an object is passed to a function or method that takes ownership of it, the wrapper
+is invalidated as we can't be sure of when the object is destroyed, unless it has a
+:ref:`virtual destructor <ownership-virt-method>` or the transfer is due to the special case
+of :ref:`parent ownership <ownership-parent>`.
- Besides being passed as argument, the called object can have its ownership changed, like
- the `setParent` method in Qt's `QObject`.
+Besides being passed as argument, the called object can have its ownership changed, like
+the `setParent` method in Qt's `QObject`.
Invalidate after use
--------------------
- Objects marked with *invalidate-after-use* in the type system description always are
- virtual method arguments provided by a C++ originated call. They should be
- invalidated right after the Python function returns (see :ref:`invalidationafteruse`).
+Objects marked with *invalidate-after-use* in the type system description always are
+virtual method arguments provided by a C++ originated call. They should be
+invalidated right after the Python function returns (see :ref:`invalidationafteruse`).
.. _ownership-virt-method:
Objects with virtual methods
----------------------------
- A little bit of implementation details (see also :ref:`codegenerationterminology`):
- virtual methods are supported by creating a C++ class, the **shell**, that inherits
- from the class with virtual methods, the native one, and override those methods to check if
- any derived class in Python also override it.
+A little bit of implementation details (see also :ref:`codegenerationterminology`):
+virtual methods are supported by creating a C++ class, the **shell**, that inherits
+from the class with virtual methods, the native one, and override those methods to check if
+any derived class in Python also override it.
- If the class has a virtual destructor (and C++ classes with virtual methods should have), this
- C++ instance invalidates the wrapper only when the overridden destructor is called.
+If the class has a virtual destructor (and C++ classes with virtual methods should have), this
+C++ instance invalidates the wrapper only when the overridden destructor is called.
- An instance of the **shell** is created when created in Python. However,
- when the object is created in C++, like in a factory method or a parameter
- to a virtual function like ``QObject::event(QEvent *)``, the wrapped object
- is a C++ instance of the native class, not the **shell** one, and we cannot
- know when it is destroyed.
+An instance of the **shell** is created when created in Python. However,
+when the object is created in C++, like in a factory method or a parameter
+to a virtual function like ``QObject::event(QEvent *)``, the wrapped object
+is a C++ instance of the native class, not the **shell** one, and we cannot
+know when it is destroyed.
.. _ownership-parent:
@@ -108,45 +108,45 @@ for any C++ library with similar behavior.
Parentship heuristics
---------------------
- As the parent-child relationship is very common, |project| tries to automatically
- infer what methods falls into the parent-child scheme, adding the extra
- directives related to ownership.
+As the parent-child relationship is very common, |project| tries to automatically
+infer what methods falls into the parent-child scheme, adding the extra
+directives related to ownership.
- This heuristic will be triggered when generating code for a method and:
+This heuristic will be triggered when generating code for a method and:
- * The function is a constructor.
- * The argument name is `parent`.
- * The argument type is a pointer to an object.
+* The function is a constructor.
+* The argument name is `parent`.
+* The argument type is a pointer to an object.
- When triggered, the heuristic will set the argument named "parent"
- as the parent of the object being created by the constructor.
+When triggered, the heuristic will set the argument named "parent"
+as the parent of the object being created by the constructor.
- The main focus of this process was to remove a lot of hand written code from
- type system when binding Qt libraries. For Qt, this heuristic works in all cases,
- but be aware that it might not when binding your own libraries.
+The main focus of this process was to remove a lot of hand written code from
+type system when binding Qt libraries. For Qt, this heuristic works in all cases,
+but be aware that it might not when binding your own libraries.
- To activate this heuristic, use the :ref:`--enable-parent-ctor-heuristic <parent-heuristic>`
- command line switch.
+To activate this heuristic, use the :ref:`--enable-parent-ctor-heuristic <parent-heuristic>`
+command line switch.
.. _return-value-heuristics:
Return value heuristics
-----------------------
- When enabled, object returned as pointer in C++ will become child of the object on which the method
- was called.
+When enabled, object returned as pointer in C++ will become child of the object on which the method
+was called.
- To activate this heuristic, use the command line switch
- :ref:`--enable-return-value-heuristic <return-heuristic>`.
+To activate this heuristic, use the command line switch
+:ref:`--enable-return-value-heuristic <return-heuristic>`.
- To disable this heuristic for specific cases, specify ``default`` as
- ownership:
+To disable this heuristic for specific cases, specify ``default`` as
+ownership:
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="0">
- <define-ownership class="target" owner="default" />
- </modify-argument>
+ <modify-argument index="0">
+ <define-ownership class="target" owner="default" />
+ </modify-argument>
Common pitfalls
===============
@@ -154,32 +154,32 @@ Common pitfalls
Not saving unowned objects references
-------------------------------------
- Sometimes when you pass an instance as argument to a method and the receiving
- instance will need that object to live indefinitely, but will not take ownership
- of the argument instance. In this case, you should hold a reference to the argument
- instance.
+Sometimes when you pass an instance as argument to a method and the receiving
+instance will need that object to live indefinitely, but will not take ownership
+of the argument instance. In this case, you should hold a reference to the argument
+instance.
- For example, let's say that you have a renderer class that will use a source class
- in a setSource method but will not take ownership of it. The following code is wrong,
- because when `render` is called the `Source` object created during the call to `setSource`
- is already destroyed.
+For example, let's say that you have a renderer class that will use a source class
+in a setSource method but will not take ownership of it. The following code is wrong,
+because when `render` is called the `Source` object created during the call to `setSource`
+is already destroyed.
- .. code-block:: python
+.. code-block:: python
- renderer.setModel(Source())
- renderer.render()
+ renderer.setModel(Source())
+ renderer.render()
- To solve this, you should hold a reference to the source object, like in
+To solve this, you should hold a reference to the source object, like in
- .. code-block:: python
+.. code-block:: python
- source = Source()
- renderer.setSource(source)
- renderer.render()
+ source = Source()
+ renderer.setSource(source)
+ renderer.render()
-Ownership Management in the Typesystem
-=======================================
+Ownership Management in the Typesystem
+======================================
Python Wrapper Code
-------------------
@@ -190,44 +190,44 @@ For this code, the ``class`` attribute takes the value ``target``
Ownership transfer from C++ to target
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- When an object currently owned by C++ has its ownership transferred
- back to the target language, the binding can know for sure when the object will be deleted and
- tie the C++ instance existence to the wrapper, calling the C++ destructor normally when the
- wrapper is deleted.
+When an object currently owned by C++ has its ownership transferred
+back to the target language, the binding can know for sure when the object will be deleted and
+tie the C++ instance existence to the wrapper, calling the C++ destructor normally when the
+wrapper is deleted.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="1">
- <define-ownership class="target" owner="target" />
- </modify-argument>
+ <modify-argument index="1">
+ <define-ownership class="target" owner="target" />
+ </modify-argument>
- A typical use case would be returning an object allocated in C++, for
- example from ``clone()`` or other factory methods.
+A typical use case would be returning an object allocated in C++, for
+example from ``clone()`` or other factory methods.
Ownership transfer from target to C++
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- In the opposite direction, when an object ownership is transferred from the target language
- to C++, the native code takes full control of the object life and you don't
- know when that object will be deleted, rendering the wrapper object invalid,
- unless you're wrapping an object with a virtual destructor,
- so you can override it and be notified of its destruction.
+In the opposite direction, when an object ownership is transferred from the target language
+to C++, the native code takes full control of the object life and you don't
+know when that object will be deleted, rendering the wrapper object invalid,
+unless you're wrapping an object with a virtual destructor,
+so you can override it and be notified of its destruction.
- By default it's safer to just render the wrapper
- object invalid and raise some error if the user tries to access
- one of this objects members or pass it as argument to some function, to avoid unpleasant segfaults.
- Also you should avoid calling the C++ destructor when deleting the wrapper.
+By default it's safer to just render the wrapper
+object invalid and raise some error if the user tries to access
+one of this objects members or pass it as argument to some function, to avoid unpleasant segfaults.
+Also you should avoid calling the C++ destructor when deleting the wrapper.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="1">
- <define-ownership class="target" owner="c++" />
- </modify-argument>
+ <modify-argument index="1">
+ <define-ownership class="target" owner="c++" />
+ </modify-argument>
- Use cases would be an returning a member object by pointer
- or passing an object by pointer into a function where the class
- takes ownership, for example
- ``QNetworkAccessManager::setCookieJar(QNetworkCookieJar *)``.
+Use cases would be an returning a member object by pointer
+or passing an object by pointer into a function where the class
+takes ownership, for example
+``QNetworkAccessManager::setCookieJar(QNetworkCookieJar *)``.
Parent-child relationship
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,11 +240,11 @@ as long as the parent is, unless some other method can take the C++ ownership aw
One of the main uses of this scheme is Qt's object system, with ownership among QObject-derived
classes, creating "trees" of instances.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="this">
- <parent index="1" action="add"/>
- </modify-argument>
+ <modify-argument index="this">
+ <parent index="1" action="add"/>
+ </modify-argument>
In this example, the instance with the method that is being invoked (indicated by 'index="this"' on
modify-argument) will be marked as a child
@@ -284,8 +284,8 @@ In this case, you should use the ``invalidate-after-use`` attribute in the
:ref:`modify-argument` tag to mark the wrapper as invalid right after the
virtual method returns.
- .. code-block:: xml
+.. code-block:: xml
- <modify-argument index="2" invalidate-after-use="yes"/>
+ <modify-argument index="2" invalidate-after-use="yes"/>
In this example the second argument will be invalidated after this method call.
diff --git a/sources/shiboken6/doc/typesystem_solving_compilation.rst b/sources/shiboken6/doc/typesystem_solving_compilation.rst
index 4b8a05447..705c2cd26 100644
--- a/sources/shiboken6/doc/typesystem_solving_compilation.rst
+++ b/sources/shiboken6/doc/typesystem_solving_compilation.rst
@@ -6,73 +6,75 @@ Solving compilation problems
suppress-warning
^^^^^^^^^^^^^^^^
- The generator will generate several warnings which may be irrelevant to the
- user. The ``suppress-warning`` node suppresses the specified warning, and it is
- a child of the :ref:`typesystem` node.
+The generator will generate several warnings which may be irrelevant to the
+user. The ``suppress-warning`` node suppresses the specified warning, and it is
+a child of the :ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <suppress-warning text="..." />
- </typesystem>
+ <typesystem>
+ <suppress-warning text="..." />
+ </typesystem>
- The **text** attribute is the warning text to suppress, and may contain the *
- wildcard (use "" to escape regular expression matching if the warning contain
- a regular "*").
+The **text** attribute is the warning text to suppress, and may contain the *
+wildcard (use "" to escape regular expression matching if the warning contain
+a regular "*").
.. _extra-includes:
extra-includes
^^^^^^^^^^^^^^
- The ``extra-includes`` node contains declarations of additional include files,
- and it can be a child of the :ref:`namespace`, :ref:`value-type`,
- :ref:`object-type` and :ref:`typesystem` and nodes.
+The ``extra-includes`` node contains declarations of additional include files,
+and it can be a child of the :ref:`namespace`, :ref:`value-type`,
+:ref:`object-type` and :ref:`typesystem` and nodes.
- The generator automatically tries to read the global header for each type but
- sometimes it is required to include extra files in the generated C++ code to
- make sure that the code compiles. These files must be listed using include
- nodes within the extra-include node:
+The generator automatically tries to read the global header for each type but
+sometimes it is required to include extra files in the generated C++ code to
+make sure that the code compiles. These files must be listed using include
+nodes within the extra-include node:
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <extra-includes>
- <include file-name="..." location="global | local"/>
- </extra-includes>
- </value-type>
+ <value-type>
+ <extra-includes>
+ <include file-name="..." location="global | local"/>
+ </extra-includes>
+ </value-type>
- The **file-name** attribute is the file to include, such as "QStringList".
- The **location** attribute is where the file is located: *global* means that
- the file is located in $INCLUDEPATH and will be included using #include <...>,
- *local* means that the file is in a local directory and will be included
- using #include "...".
+The **file-name** attribute is the file to include, such as "QStringList".
+The **location** attribute is where the file is located: *global* means that
+the file is located in $INCLUDEPATH and will be included using #include <...>,
+*local* means that the file is in a local directory and will be included
+using #include "...".
- When specified as a child of the :ref:`typesystem` node, the include
- directives are added to the module source file which contains
- the type converter and registration code. It can be used to specify
- additional includes required for the converter code snippets.
+When specified as a child of the :ref:`typesystem` node, the include
+directives are added to the module source file which contains
+the type converter and registration code. It can be used to specify
+additional includes required for the converter code snippets.
+
+.. _include-element:
include
^^^^^^^
- The ``include`` node specifies the name and location of a file that must be
- included, and it is a child of the :ref:`namespace`, :ref:`value-type`,
- :ref:`object-type` or :ref:`extra-includes` node.
+The ``include`` node specifies the name and location of a file that must be
+included, and it is a child of the :ref:`namespace`, :ref:`value-type`,
+:ref:`object-type` or :ref:`extra-includes` node.
- The generator automatically tries to read the global header for each type. Use
- the include node to override this behavior, providing an alternative file. The
- include node can also be used to specify extra include files.
+The generator automatically tries to read the global header for each type. Use
+the include node to override this behavior, providing an alternative file. The
+include node can also be used to specify extra include files.
- .. code-block:: xml
+.. code-block:: xml
- <value-type>
- <include file-name="..."
- location="global | local"/>
- </value-type>
+ <value-type>
+ <include file-name="..."
+ location="global | local"/>
+ </value-type>
- The **file-name** attribute is the file to include, such as "QStringList".
- The **location** attribute is where the file is located: *global* means that
- the file is located in $INCLUDEPATH and will be included using #include <...>,
- *local* means that the file is in a local directory and will be included
- using #include "...".
+The **file-name** attribute is the file to include, such as "QStringList".
+The **location** attribute is where the file is located: *global* means that
+the file is located in $INCLUDEPATH and will be included using #include <...>,
+*local* means that the file is in a local directory and will be included
+using #include "...".
diff --git a/sources/shiboken6/doc/typesystem_specialfunctions.rst b/sources/shiboken6/doc/typesystem_specialfunctions.rst
index 5c0c52663..78a6ff489 100644
--- a/sources/shiboken6/doc/typesystem_specialfunctions.rst
+++ b/sources/shiboken6/doc/typesystem_specialfunctions.rst
@@ -13,15 +13,15 @@ names, this is done using the :ref:`add-function` tag.
The special function names are:
- ============= =============================================== ==================== ===================
- Function name Parameters Return type CPython equivalent
- ============= =============================================== ==================== ===================
- __len__ PyObject* self Py_ssize_t PySequence_Size
- __getitem__ PyObject* self, Py_ssize_t _i PyObject* PySequence_GetItem
- __setitem__ PyObject* self, Py_ssize_t _i, PyObject* _value int PySequence_SetItem
- __contains__ PyObject* self, PyObject* _value int PySequence_Contains
- __concat__ PyObject* self, PyObject* _other PyObject* PySequence_Concat
- ============= =============================================== ==================== ===================
+============= =============================================== ==================== ===================
+Function name Parameters Return type CPython equivalent
+============= =============================================== ==================== ===================
+__len__ PyObject* self Py_ssize_t PySequence_Size
+__getitem__ PyObject* self, Py_ssize_t _i PyObject* PySequence_GetItem
+__setitem__ PyObject* self, Py_ssize_t _i, PyObject* _value int PySequence_SetItem
+__contains__ PyObject* self, PyObject* _value int PySequence_Contains
+__concat__ PyObject* self, PyObject* _other PyObject* PySequence_Concat
+============= =============================================== ==================== ===================
You just need to inform the function name to the :ref:`add-function` tag, without any
parameter or return type information, when you do it, |project| will create a C
@@ -47,8 +47,8 @@ in boolean expressions. In C++, this is commonly implemented as
In Python, the function ``__bool__`` is used for this. shiboken can generate
this functions depending on the command line options
-:ref:`--use-operator-bool-as-nb_nonzero <use-operator-bool-as-nb-nonzero>`
-and :ref:`--use-isnull-as-nb_nonzero <use-isnull-as-nb-nonzero>`,
+:ref:`--use-operator-bool-as-nb-bool <use-operator-bool-as-nb-bool>`
+and :ref:`--use-isnull-as-nb-bool <use-isnull-as-nb-bool>`,
which can be overridden by specifying the boolean attributes
**isNull** or **operator-bool** on the :ref:`value-type` or :ref:`object-type`
elements in typesystem XML.
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 4f5817402..f65b79bb4 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -30,751 +30,835 @@ of the underlying parser.
typesystem
^^^^^^^^^^
- This is the root node containing all the type system information.
- It may contain :ref:`add-function`, :ref:`container-type`,
- :ref:`custom-type`, :ref:`enum-type`, :ref:`extra-includes`, :ref:`function`,
- :ref:`load-typesystem`, :ref:`namespace`, :ref:`object-type`,
- :ref:`primitive-type`, :ref:`rejection`, :ref:`smart-pointer-type`,
- :ref:`suppress-warning`, :ref:`template`, :ref:`system_include`,
- :ref:`typedef-type` or :ref:`value-type` child nodes.
+This is the root node containing all the type system information.
+It may contain :ref:`add-function`, :ref:`container-type`,
+:ref:`custom-type`, :ref:`enum-type`, :ref:`extra-includes`, :ref:`function`,
+:ref:`load-typesystem`, :ref:`namespace`, :ref:`object-type`,
+:ref:`opaque-container`,
+:ref:`primitive-type`, :ref:`rejection`, :ref:`smart-pointer-type`,
+:ref:`suppress-warning`, :ref:`template`, :ref:`system_include`,
+:ref:`typedef-type` or :ref:`value-type` child nodes.
- It can have a number of attributes, described below.
+It can have a number of attributes, described below.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem package="..." default-superclass="..." allow-thread="..."
- exception-handling="..." snake-case="yes | no | both" >
- </typesystem>
+ <typesystem package="..."
+ submodule-of="..."
+ allow-thread="..."
+ exception-handling="..."
+ snake-case="yes | no | both"
+ namespace-begin="..."
+ namespace-end="..." >
+ </typesystem>
+
+The **package** attribute is a string describing the package to be used,
+e.g. "QtCore".
- The **package** attribute is a string describing the package to be used,
- e.g. "QtCore".
- The *optional* **default-superclass** attribute is the canonical C++ base class
- name of all objects, e.g., "object".
+The *optional* **submodule-of** attribute specifies the name of a module to
+which the module is added as a sub-module. This requires adapting the
+installation directory of the module accordingly.
- The *optional* attributes **allow-thread** and **exception-handling**
- specify the default handling for the corresponding function modification
- (see :ref:`modify-function`).
+The *optional* attributes **allow-thread** and **exception-handling**
+specify the default handling for the corresponding function modification
+(see :ref:`modify-function`).
- The *optional* **snake-case** attribute specifies whether function
- and field names will be automatically changed to the snake case
- style that is common in Python (for example, ``snakeCase`` will be
- changed to ``snake_case``).
+The *optional* **snake-case** attribute specifies whether function
+and field names will be automatically changed to the snake case
+style that is common in Python (for example, ``snakeCase`` will be
+changed to ``snake_case``).
- The value ``both`` means that the function or field will be exposed
- under both its original name and the snake case version. There are
- limitations to this though:
+The value ``both`` means that the function or field will be exposed
+under both its original name and the snake case version. There are
+limitations to this though:
- - When overriding a virtual function of a C++ class in Python,
- the snake case name must be used.
+- When overriding a virtual function of a C++ class in Python,
+ the snake case name must be used.
- - When static and non-static overloads of a class member function
- exist (as is the case for example for ``QFileInfo::exists()``),
- the snake case name must be used.
+- When static and non-static overloads of a class member function
+ exist (as is the case for example for ``QFileInfo::exists()``),
+ the snake case name must be used.
+
+The *optional* **namespace-begin** and **namespace-end** attributes will be
+generated around the forward declarations in the module header. This is
+intended for libraries which can optionally use inline namespaces
+to allow for linking several versions of them together.
+For example, for *Qt*, one would specify ``QT_BEGIN_NAMESPACE``,
+``QT_END_NAMESPACE``, respectively.
.. _load-typesystem:
load-typesystem
^^^^^^^^^^^^^^^
- The ``load-typesystem`` node specifies which type systems to load when mapping
- multiple libraries to another language or basing one library on another, and
- it is a child of the :ref:`typesystem` node.
+The ``load-typesystem`` node specifies which type systems to load when mapping
+multiple libraries to another language or basing one library on another, and
+it is a child of the :ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <load-typesystem name="..." generate="yes | no" />
- </typesystem>
+ <typesystem>
+ <load-typesystem name="..." generate="yes | no" />
+ </typesystem>
- The **name** attribute is the filename of the typesystem to load, the
- **generate** attribute specifies whether code should be generated or not. The
- later must be specified when basing one library on another, making the generator
- able to understand inheritance hierarchies, primitive mapping, parameter types
- in functions, etc.
+The **name** attribute is the filename of the typesystem to load, the
+**generate** attribute specifies whether code should be generated or not. The
+later must be specified when basing one library on another, making the generator
+able to understand inheritance hierarchies, primitive mapping, parameter types
+in functions, etc.
- Most libraries will be based on both the QtCore and QtGui modules, in which
- case code generation for these libraries will be disabled.
+Most libraries will be based on both the QtCore and QtGui modules, in which
+case code generation for these libraries will be disabled.
.. _rejection:
rejection
^^^^^^^^^
- The ``rejection`` node rejects the given class, or the specified function
- or field, and it is a child of the :ref:`typesystem` node.
+The ``rejection`` node rejects the given class, or the specified function
+or field, and it is a child of the :ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <rejection class="..."
- function-name="..."
- field-name="..." />
- </typesystem>
+ <typesystem>
+ <rejection class="..."
+ function-name="..."
+ argument-type="..."
+ field-name="..." />
+ </typesystem>
- The **class** attribute is the C++ class name of the class to reject. Use the
- *optional* **function-name** or **field-name** attributes to reject a particular
- function or field. Note that the **field-name** and **function-name** cannot
- be specified at the same time. To remove all occurrences of a given field or
- function, set the class attribute to \*.
+The **class** attribute is the C++ class name of the class to reject. Use
+the *optional* **function-name**, **argument-type**, or **field-name**
+attributes to reject a particular function, function with arguments of a
+particular type, or a field. Note that the **field-name** and
+**function-name**/**argument-type** cannot be specified at the same time.
+To remove all occurrences of a given field or function, set the class
+attribute to \*.
.. _primitive-type:
primitive-type
^^^^^^^^^^^^^^
- The ``primitive-type`` node describes how a primitive type is mapped from C++ to
- the target language, and is a child of the :ref:`typesystem` node. It may
- contain :ref:`conversion-rule` child nodes. Note that most primitives are
- already specified in the QtCore typesystem (see :ref:`primitive-cpp-types`).
-
- .. code-block:: xml
-
- <typesystem>
- <primitive-type name="..."
- since="..."
- until="..."
- target-lang-api-name="..."
- default-constructor="..."
- preferred-conversion="yes | no" />
- view-on="..."
- </typesystem>
+The ``primitive-type`` node describes how a primitive type is mapped from C++ to
+the target language, and is a child of the :ref:`typesystem` node. It may
+contain :ref:`conversion-rule` child nodes. Note that most primitives are
+already specified in the QtCore typesystem (see :ref:`primitive-cpp-types`).
- The **name** attribute is the name of the primitive in C++.
+.. code-block:: xml
+
+ <typesystem>
+ <primitive-type name="..."
+ since="..."
+ until="..."
+ target-lang-api-name="..."
+ default-constructor="..."
+ preferred-conversion="yes | no"
+ view-on="..." />
+ </typesystem>
- The optional **target-lang-api-name** attribute is the name of the
- primitive type in the target language, defaulting to the **name** attribute.
+The **name** attribute is the name of the primitive in C++.
- The *optional* **since** value is used to specify the API version in which
- the type was introduced.
+The optional **target-lang-api-name** attribute is the name of the
+primitive type in the target language, defaulting to the **name** attribute.
- Similarly, the *optional* **until** value can be used to specify the API
- version in which the type will be obsoleted.
+The *optional* **since** value is used to specify the API version in which
+the type was introduced.
- If the *optional* **preferred-conversion** attribute is set to *no*, it
- indicates that this version of the primitive type is not the preferred C++
- equivalent of the target language type. For example, in Python both "qint64"
- and "long long" become "long" but we should prefer the "qint64" version. For
- this reason we mark "long long" with preferred-conversion="no".
+Similarly, the *optional* **until** value can be used to specify the API
+version in which the type will be obsoleted.
- The *optional* **default-constructor** specifies the minimal constructor
- call to build one value of the primitive-type. This is not needed when the
- primitive-type may be built with a default constructor (the one without
- arguments).
+If the *optional* **preferred-conversion** attribute is set to *no*, it
+indicates that this version of the primitive type is not the preferred C++
+equivalent of the target language type. For example, in Python both "qint64"
+and "long long" become "long" but we should prefer the "qint64" version. For
+this reason we mark "long long" with preferred-conversion="no".
- The *optional* **preferred-conversion** attribute tells how to build a default
- instance of the primitive type. It should be a constructor call capable of
- creating a instance of the primitive type. Example: a class "Foo" could have
- a **preferred-conversion** value set to "Foo()". Usually this attribute is
- used only for classes declared as primitive types and not for primitive C++
- types, but that depends on the application using *ApiExtractor*.
+The *optional* **default-constructor** specifies the minimal constructor
+call to build one value of the primitive-type. This is not needed when the
+primitive-type may be built with a default constructor (the one without
+arguments).
- The *optional* **view-on** attribute specifies that the type is a view
- class like std::string_view or QStringView which has a constructor
- accepting another type like std::string or QString. Since typically
- no values can be assigned to view classes, no target-to-native conversion
- can be generated for them. Instead, an instance of the viewed class should
- be instantiated and passed to functions using the view class
- for argument types.
+The *optional* **preferred-conversion** attribute tells how to build a default
+instance of the primitive type. It should be a constructor call capable of
+creating a instance of the primitive type. Example: a class "Foo" could have
+a **preferred-conversion** value set to "Foo()". Usually this attribute is
+used only for classes declared as primitive types and not for primitive C++
+types, but that depends on the application using *ApiExtractor*.
- See :ref:`predefined_templates` for built-in templates for standard type
- conversion rules.
+The *optional* **view-on** attribute specifies that the type is a view
+class like std::string_view or QStringView which has a constructor
+accepting another type like std::string or QString. Since typically
+no values can be assigned to view classes, no target-to-native conversion
+can be generated for them. Instead, an instance of the viewed class should
+be instantiated and passed to functions using the view class
+for argument types.
+
+See :ref:`predefined_templates` for built-in templates for standard type
+conversion rules.
.. _namespace:
namespace-type
^^^^^^^^^^^^^^
- The ``namespace-type`` node maps the given C++ namespace to the target
- language, and it is a child of the :ref:`typesystem` node or other
- ``namespace-type`` nodes. It may contain :ref:`add-function`,
- :ref:`declare-function`, :ref:`enum-type`, :ref:`extra-includes`,
- :ref:`modify-function`, ``namespace-type``, :ref:`object-type`,
- :ref:`smart-pointer-type`, :ref:`typedef-type` or :ref:`value-type`
- child nodes.
-
- .. code-block:: xml
-
- <typesystem>
- <namespace-type name="..."
- visible="true | auto | false"
- generate="yes | no"
- generate-using="yes | no"
- package="..."
- since="..."
- revision="..." />
- </typesystem>
+The ``namespace-type`` node maps the given C++ namespace to the target
+language, and it is a child of the :ref:`typesystem` node or other
+``namespace-type`` nodes. It may contain :ref:`add-function`,
+:ref:`declare-function`, :ref:`enum-type`, :ref:`extra-includes`,
+:ref:`include-element`, :ref:`modify-function`, ``namespace-type``,
+:ref:`object-type`, :ref:`smart-pointer-type`, :ref:`typedef-type` or :ref:`value-type`
+child nodes.
+
+.. code-block:: xml
+
+ <typesystem>
+ <namespace-type name="..."
+ visible="true | auto | false"
+ generate="yes | no"
+ generate-using="yes | no"
+ package="..."
+ since="..."
+ extends = "..."
+ files = "..."
+ revision="..." />
+ </typesystem>
- The **name** attribute is the name of the namespace, e.g., "Qt".
+The **name** attribute is the name of the namespace, e.g., "Qt".
- The *optional* **visible** attribute is used specify whether the
- namespace is visible in the target language name. Its default value is
- **auto**. It means that normal namespaces are visible, but inline namespaces
- (as introduced in C++ 11) will not be visible.
+The *optional* **visible** attribute is used specify whether the
+namespace is visible in the target language name. Its default value is
+**auto**. It means that normal namespaces are visible, but inline namespaces
+(as introduced in C++ 11) will not be visible.
- The detection of inline namespaces requires shiboken to be built
- using LLVM 9.0.
+The detection of inline namespaces requires shiboken to be built
+using LLVM 9.0.
- The *optional* **generate** is a legacy attribute. Specifying
- **no** is equivalent to **visible="false"**.
+The *optional* **generate** is a legacy attribute. Specifying
+**no** is equivalent to **visible="false"**.
- The *optional* **generate-using** attribute specifies whether
- ``using namespace`` is generated into the wrapper code for classes within
- the namespace (default: **yes**). This ensures for example that not fully
- qualified enumeration values of default argument values compile.
- However, in rare cases, it might cause ambiguities and can then be turned
- off.
+The *optional* **generate-using** attribute specifies whether
+``using namespace`` is generated into the wrapper code for classes within
+the namespace (default: **yes**). This ensures for example that not fully
+qualified enumeration values of default argument values compile.
+However, in rare cases, it might cause ambiguities and can then be turned
+off.
- The **package** attribute can be used to override the package of the type system.
+The **package** attribute can be used to override the package of the type system.
- The *optional* **since** value is used to specify the API version of this type.
+The *optional* **since** value is used to specify the API version of this type.
- The **revision** attribute can be used to specify a revision for each type, easing the
- production of ABI compatible bindings.
+The **revision** attribute can be used to specify a revision for each type, easing the
+production of ABI compatible bindings.
+
+The *optional* **extends** attribute specifies the module name where the given
+namespace first occurs in case of a namespace spanning several modules. For
+example, in Qt, the namespace ``Qt`` first occurs in the ``QtCore`` module and
+is further populated in the ``QtGui`` module. ``QtGui.Qt`` will then be
+generated extending ``QtCore.Qt`` if **extends** is specified.
+
+The *optional* **file** attribute specifies a regular expression matching the
+include files whose contents are to be associated with the current module in
+case of a namespace spanning several modules.
.. _enum-type:
enum-type
^^^^^^^^^
- The ``enum-type`` node maps the given enum from C++ to the target language,
- and it is a child of the :ref:`typesystem` node. Use
- :ref:`reject-enum-value` child nodes to reject values.
-
- .. code-block:: xml
-
- <typesystem>
- <enum-type name="..."
- identified-by-value="..."
- class="yes | no"
- since="..."
- flags="yes | no"
- flags-revision="..."
- lower-bound="..."
- upper-bound="..."
- force-integer="yes | no"
- extensible="yes | no"
- revision="..." />
- </typesystem>
+The ``enum-type`` node maps the given enum from C++ to the target language,
+and it is a child of the :ref:`typesystem` node. Use
+:ref:`reject-enum-value` child nodes to reject values.
- The **name** attribute is the fully qualified C++ name of the enum
- (e.g.,"Qt::FillRule"). If the *optional* **flags** attribute is set to *yes*
- (the default is *no*), the generator will expect an existing QFlags<T> for the
- given enum type. The **lower-bound** and **upper-bound** attributes are used
- to specify runtime bounds checking for the enum value. The value must be a
- compilable target language statement, such as "QGradient.Spread.PadSpread"
- (taking again Python as an example). If the **force-integer** attribute is
- set to *yes* (the default is *no*), the generated target language code will
- use the target language integers instead of enums. And finally, the
- **extensible** attribute specifies whether the given enum can be extended
- with user values (the default is *no*).
+.. code-block:: xml
+
+ <typesystem>
+ <enum-type name="..."
+ identified-by-value="..."
+ class="yes | no"
+ since="..."
+ flags="yes | no"
+ flags-revision="..."
+ cpp-type = "..."
+ doc-file = "..."
+ python-type = "IntEnum | IntFlag"
+ lower-bound="..."
+ upper-bound="..."
+ force-integer="yes | no"
+ extensible="yes | no"
+ revision="..." />
+ </typesystem>
+
+The **name** attribute is the fully qualified C++ name of the enum
+(e.g.,"Qt::FillRule"). If the *optional* **flags** attribute is set to *yes*
+(the default is *no*), the generator will expect an existing QFlags<T> for the
+given enum type. The **lower-bound** and **upper-bound** attributes are used
+to specify runtime bounds checking for the enum value. The value must be a
+compilable target language statement, such as "QGradient.Spread.PadSpread"
+(taking again Python as an example). If the **force-integer** attribute is
+set to *yes* (the default is *no*), the generated target language code will
+use the target language integers instead of enums. And finally, the
+**extensible** attribute specifies whether the given enum can be extended
+with user values (the default is *no*).
+
+The *optional* **since** value is used to specify the API version of this type.
+
+The attribute **identified-by-value** helps to specify anonymous enums using the
+name of one of their values, which is unique for the anonymous enum scope.
+Notice that the **enum-type** tag can either have **name** or **identified-by-value**
+but not both.
- The *optional* **since** value is used to specify the API version of this type.
+The *optional* **python-type** attribute specifies the underlying
+Python type.
- The attribute **identified-by-value** helps to specify anonymous enums using the
- name of one of their values, which is unique for the anonymous enum scope.
- Notice that the **enum-type** tag can either have **name** or **identified-by-value**
- but not both.
+The *optional* **cpp-type** attribute specifies a C++ to be used for
+casting values. This can be useful for large values triggering MSVC
+signedness issues.
- The **revision** attribute can be used to specify a revision for each type, easing the
- production of ABI compatible bindings.
+The *optional* **doc-file** attribute specifies the base name of the C++ or
+``.qdoc`` file indicated by ``\relates`` or ``\headerfile`` in ``qdoc``, to
+which the documentation of the enumeration is to be added and displayed in the
+case its a global enumeration. This attribute is for ``qdoc`` only.
- The **flags-revision** attribute has the same purposes of **revision** attribute but
- is used for the QFlag related to this enum.
+The **revision** attribute can be used to specify a revision for each type, easing the
+production of ABI compatible bindings.
+
+The **flags-revision** attribute has the same purposes of **revision** attribute but
+is used for the QFlag related to this enum.
.. _reject-enum-value:
reject-enum-value
^^^^^^^^^^^^^^^^^
- The ``reject-enum-value`` node rejects the enum value specified by the
- **name** attribute, and it is a child of the :ref:`enum-type` node.
+The ``reject-enum-value`` node rejects the enum value specified by the
+**name** attribute, and it is a child of the :ref:`enum-type` node.
- .. code-block:: xml
+.. code-block:: xml
- <enum-type>
- <reject-enum-value name="..."/>
- </enum-type>
+ <enum-type>
+ <reject-enum-value name="..."/>
+ </enum-type>
- This node is used when a C++ enum implementation has several identical numeric
- values, some of which are typically obsolete.
+This node is used when a C++ enum implementation has several identical numeric
+values, some of which are typically obsolete.
.. _value-type:
value-type
^^^^^^^^^^
- The ``value-type`` node indicates that the given C++ type is mapped onto the target
- language as a value type. This means that it is an object passed by value on C++,
- i.e. it is stored in the function call stack. It is a child of the :ref:`typesystem`
- node or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`,
- :ref:`declare-function`, :ref:`conversion-rule`, :ref:`enum-type`,
- :ref:`extra-includes`, :ref:`modify-function`, :ref:`object-type`,
- :ref:`smart-pointer-type`, :ref:`typedef-type` or further ``value-type``
- child nodes.
-
- .. code-block:: xml
-
- <typesystem>
- <value-type name="..." since="..."
- copyable="yes | no"
- allow-thread="..."
- disable-wrapper="yes | no"
- exception-handling="..."
- generate-functions="..."
- isNull ="yes | no"
- operator-bool="yes | no"
- hash-function="..."
- private="yes | no"
- qt-register-metatype = "yes | no | base"
- stream="yes | no"
- default-constructor="..."
- revision="..."
- snake-case="yes | no | both" />
- </typesystem>
+The ``value-type`` node indicates that the given C++ type is mapped onto the target
+language as a value type. This means that it is an object passed by value on C++,
+i.e. it is stored in the function call stack. It is a child of the :ref:`typesystem`
+node or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`,
+:ref:`configuration-element`, :ref:`declare-function`, :ref:`conversion-rule`,
+:ref:`enum-type`, :ref:`extra-includes`, :ref:`include-element`, :ref:`modify-function`,
+:ref:`object-type`, :ref:`smart-pointer-type`, :ref:`typedef-type` or further
+``value-type`` child nodes.
- The **name** attribute is the fully qualified C++ class name, such as
- "QMatrix" or "QPainterPath::Element". The **copyable** attribute is used to
- force or not specify if this type is copyable. The *optional* **hash-function**
- attribute informs the function name of a hash function for the type.
+.. code-block:: xml
+
+ <typesystem>
+ <value-type name="..." since="..."
+ copyable="yes | no"
+ allow-thread="..."
+ disable-wrapper="yes | no"
+ exception-handling="..."
+ generate-functions="..."
+ isNull ="yes | no"
+ operator-bool="yes | no"
+ hash-function="..."
+ private="yes | no"
+ qt-register-metatype = "yes | no | base"
+ stream="yes | no"
+ default-constructor="..."
+ revision="..."
+ snake-case="yes | no | both" />
+ </typesystem>
- The *optional* attribute **stream** specifies whether this type will be able to
- use externally defined operators, like QDataStream << and >>. If equals to **yes**,
- these operators will be called as normal methods within the current class.
+The **name** attribute is the fully qualified C++ class name, such as
+"QMatrix" or "QPainterPath::Element". The **copyable** attribute is used to
+force or not specify if this type is copyable. The *optional* **hash-function**
+attribute informs the function name of a hash function for the type.
- The *optional* **since** value is used to specify the API version of this type.
+The *optional* attribute **stream** specifies whether this type will be able to
+use externally defined operators, like QDataStream << and >>. If equals to **yes**,
+these operators will be called as normal methods within the current class.
- The *optional* **default-constructor** specifies the minimal constructor
- call to build one instance of the value-type. This is not needed when the
- value-type may be built with a default constructor (the one without arguments).
- Usually a code generator may guess a minimal constructor for a value-type based
- on its constructor signatures, thus **default-constructor** is used only in
- very odd cases.
+The *optional* **since** value is used to specify the API version of this type.
- For the *optional* **disable-wrapper** and **generate-functions**
- attributes, see :ref:`object-type`.
+The *optional* **default-constructor** specifies the minimal constructor
+call to build one instance of the value-type. This is not needed when the
+value-type may be built with a default constructor (the one without arguments).
+Usually a code generator may guess a minimal constructor for a value-type based
+on its constructor signatures, thus **default-constructor** is used only in
+very odd cases.
- For the *optional* **private** attribute, see :ref:`private_types`.
+For the *optional* **disable-wrapper** and **generate-functions**
+attributes, see :ref:`object-type`.
- The *optional* **qt-register-metatype** attribute determines whether
- a Qt meta type registration is generated for ``name``. By
- default, this is generated for non-abstract, default-constructible
- types for usage in signals and slots.
- The value ``base`` means that the registration will be generated for the
- class in question but not for inheriting classes. This allows for
- restricting the registration to base classes of type hierarchies.
+For the *optional* **private** attribute, see :ref:`private_types`.
- The **revision** attribute can be used to specify a revision for each type, easing the
- production of ABI compatible bindings.
+The *optional* **qt-register-metatype** attribute determines whether
+a Qt meta type registration is generated for ``name``. By
+default, this is generated for non-abstract, default-constructible
+types for usage in signals and slots.
+The value ``base`` means that the registration will be generated for the
+class in question but not for inheriting classes. This allows for
+restricting the registration to base classes of type hierarchies.
- The *optional* attributes **allow-thread** and **exception-handling**
- specify the default handling for the corresponding function modification
- (see :ref:`modify-function`).
+The **revision** attribute can be used to specify a revision for each type, easing the
+production of ABI compatible bindings.
- The *optional* **snake-case** attribute allows for overriding the value
- specified on the **typesystem** element.
+The *optional* attributes **allow-thread** and **exception-handling**
+specify the default handling for the corresponding function modification
+(see :ref:`modify-function`).
- The *optional* **isNull** and **operator-bool** attributes can be used
- to override the command line setting for generating bool casts
- (see :ref:`bool-cast`).
+The *optional* **snake-case** attribute allows for overriding the value
+specified on the **typesystem** element.
+
+The *optional* **isNull** and **operator-bool** attributes can be used
+to override the command line setting for generating bool casts
+(see :ref:`bool-cast`).
.. _object-type:
object-type
^^^^^^^^^^^
- The object-type node indicates that the given C++ type is mapped onto the target
- language as an object type. This means that it is an object passed by pointer on
- C++ and it is stored on the heap. It is a child of the :ref:`typesystem` node
- or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`,
- :ref:`declare-function`, :ref:`enum-type`, :ref:`extra-includes`,
- :ref:`modify-function`, ``object-type``, :ref:`smart-pointer-type`,
- :ref:`typedef-type` or :ref:`value-type` child nodes.
-
- .. code-block:: xml
-
- <typesystem>
- <object-type name="..."
- since="..."
- copyable="yes | no"
- allow-thread="..."
- disable-wrapper="yes | no"
- exception-handling="..."
- generate-functions="..."
- force-abstract="yes | no"
- hash-function="..."
- isNull ="yes | no"
- operator-bool="yes | no"
- parent-management="yes | no"
- polymorphic-id-expression="..."
- polymorphic-name-function="..."
- private="yes | no"
- qt-register-metatype = "yes | no | base"
- stream="yes | no"
- revision="..."
- snake-case="yes | no | both" />
- </typesystem>
+The object-type node indicates that the given C++ type is mapped onto the target
+language as an object type. This means that it is an object passed by pointer on
+C++ and it is stored on the heap. It is a child of the :ref:`typesystem` node
+or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`,
+:ref:`configuration-element`, :ref:`declare-function`, :ref:`enum-type`,
+:ref:`extra-includes`, :ref:`include-element`, :ref:`modify-function`,
+``object-type``, :ref:`smart-pointer-type`, :ref:`typedef-type` or
+:ref:`value-type` child nodes.
+
+.. code-block:: xml
+
+ <typesystem>
+ <object-type name="..."
+ since="..."
+ copyable="yes | no"
+ allow-thread="..."
+ disable-wrapper="yes | no"
+ exception-handling="..."
+ generate-functions="..."
+ force-abstract="yes | no"
+ hash-function="..."
+ isNull ="yes | no"
+ operator-bool="yes | no"
+ parent-management="yes | no"
+ polymorphic-id-expression="..."
+ polymorphic-name-function="..."
+ polymorphic-base="yes | no"
+ private="yes | no"
+ qt-metaobject="yes | no"
+ qt-register-metatype = "yes | no | base"
+ stream="yes | no"
+ revision="..."
+ snake-case="yes | no | both" />
+ </typesystem>
- The **name** attribute is the fully qualified C++ class name. If there is no
- C++ base class, the default-superclass attribute can be used to specify a
- superclass for the given type, in the generated target language API. The
- **copyable** and **hash-function** attributes are the same as described for
- :ref:`value-type`.
-
- The *optional* **force-abstract** attribute forces the class to be
- abstract, disabling its instantiation. The generator will normally detect
- this automatically unless the class inherits from an abstract base class
- that is not in the type system.
-
- The *optional* **disable-wrapper** attribute disables the generation of a
- **C++ Wrapper** (see :ref:`codegenerationterminology`). This will
- effectively disable overriding virtuals methods in Python for the class.
- It can be used when the class cannot be instantiated from Python and
- its virtual methods pose some problem for the code generator (by returning
- references, or using a default value that cannot be generated for a
- parameter, or similar).
-
- For the *optional* **private** attribute, see :ref:`private_types`.
-
- The *optional* **qt-register-metatype** attribute determines whether
- a Qt meta type registration is generated for ``name *``. By
- default, this is only generated for non-QObject types for usage
- in signals and slots.
- The value ``base`` means that the registration will be generated for the
- class in question but not for inheriting classes. This allows for
- restricting the registration to base classes of type hierarchies.
-
- The *optional* attribute **stream** specifies whether this type will be able to
- use externally defined operators, like QDataStream << and >>. If equals to **yes**,
- these operators will be called as normal methods within the current class.
-
- The *optional* **since** value is used to specify the API version of this type.
-
- The **revision** attribute can be used to specify a revision for each type, easing the
- production of ABI compatible bindings.
-
- The *optional* attributes **allow-thread** and **exception-handling**
- specify the default handling for the corresponding function modification
- (see :ref:`modify-function`).
-
- The *optional* **generate-functions** specifies a semicolon-separated
- list of function names or minimal signatures to be generated.
- This allows for restricting the functions for which bindings are generated.
- This also applies to virtual functions; so, all abstract functions
- need to be listed to prevent non-compiling code to be generated.
- If nothing is specified, bindings for all suitable functions are
- generated. Note that special functions (constructors, etc),
- cannot be specified.
-
- The *optional* **snake-case** attribute allows for overriding the value
- specified on the **typesystem** element.
-
- The *optional* **isNull** and **operator-bool** attributes can be used
- to override the command line setting for generating bool casts
- (see :ref:`bool-cast`).
-
- The *optional* **parent-management** attribute specifies that the class is
- used for building object trees consisting of parents and children, for
- example, user interfaces like the ``QWidget`` classes. For those classes,
- the heuristics enabled by :ref:`ownership-parent-heuristics` and
- :ref:`return-value-heuristics` are applied to automatically set parent
- relationships. Compatibility note: In shiboken 6, when no class of the
- type system has this attribute set, the heuristics will be applied
- to all classes. In shiboken 7, it will be mandatory to set the
- attribute.
-
- The *optional* **polymorphic-id-expression** attribute specifies an
- expression checking whether a base class pointer is of the matching
- type. For example, in a ``virtual eventHandler(BaseEvent *e)``
- function, this is used to construct a Python wrapper matching
- the derived class (for example, a ``MouseEvent`` or similar).
-
- The *optional* **polymorphic-name-function** specifies the name of a
- function returning the type name of a derived class on the base class
- type entry. Normally, ``typeid(ptr).name()`` is used for this.
- However, this fails if the type hierarchy does not have virtual functions.
- In this case, a function is required which typically decides depending
- on some type enumeration.
+The **name** attribute is the fully qualified C++ class name. If there is no
+C++ base class, the default-superclass attribute can be used to specify a
+superclass for the given type, in the generated target language API. The
+**copyable** and **hash-function** attributes are the same as described for
+:ref:`value-type`.
+
+The *optional* **force-abstract** attribute forces the class to be
+abstract, disabling its instantiation. The generator will normally detect
+this automatically unless the class inherits from an abstract base class
+that is not in the type system.
+
+The *optional* **disable-wrapper** attribute disables the generation of a
+**C++ Wrapper** (see :ref:`codegenerationterminology`). This will
+effectively disable overriding virtuals methods in Python for the class.
+It can be used when the class cannot be instantiated from Python and
+its virtual methods pose some problem for the code generator (by returning
+references, or using a default value that cannot be generated for a
+parameter, or similar).
+
+For the *optional* **private** attribute, see :ref:`private_types`.
+
+The *optional* **qt-metaobject** attribute specifies whether
+the special Qt virtual functions ``metaObject()``,
+``metaCall()``, and ``metaCast()`` are generated. For classes
+using dynamic meta objects, for example, ``QDBusInterface``,
+it can be turned off.
+
+The *optional* **qt-register-metatype** attribute determines whether
+a Qt meta type registration is generated for ``name *``. By
+default, this is only generated for non-QObject types for usage
+in signals and slots.
+The value ``base`` means that the registration will be generated for the
+class in question but not for inheriting classes. This allows for
+restricting the registration to base classes of type hierarchies.
+
+The *optional* attribute **stream** specifies whether this type will be able to
+use externally defined operators, like QDataStream << and >>. If equals to **yes**,
+these operators will be called as normal methods within the current class.
+
+The *optional* **since** value is used to specify the API version of this type.
+
+The **revision** attribute can be used to specify a revision for each type, easing the
+production of ABI compatible bindings.
+
+The *optional* attributes **allow-thread** and **exception-handling**
+specify the default handling for the corresponding function modification
+(see :ref:`modify-function`).
+
+The *optional* **generate-functions** specifies a semicolon-separated
+list of function names or minimal signatures to be generated.
+This allows for restricting the functions for which bindings are generated.
+This also applies to virtual functions; so, all abstract functions
+need to be listed to prevent non-compiling code to be generated.
+If nothing is specified, bindings for all suitable functions are
+generated. Note that special functions (constructors, etc),
+cannot be specified.
+
+The *optional* **snake-case** attribute allows for overriding the value
+specified on the **typesystem** element.
+
+The *optional* **isNull** and **operator-bool** attributes can be used
+to override the command line setting for generating bool casts
+(see :ref:`bool-cast`).
+
+The *optional* **parent-management** attribute specifies that the class is
+used for building object trees consisting of parents and children, for
+example, user interfaces like the ``QWidget`` classes. For those classes,
+the heuristics enabled by :ref:`ownership-parent-heuristics` and
+:ref:`return-value-heuristics` are applied to automatically set parent
+relationships. Compatibility note: In shiboken 6, when no class of the
+type system has this attribute set, the heuristics will be applied
+to all classes. In shiboken 7, it will be mandatory to set the
+attribute.
+
+For the *optional* **polymorphic-id-expression**, **polymorphic-name-function**
+and **polymorphic-base** attributes, see :ref:`typediscovery-attributes`.
interface-type
^^^^^^^^^^^^^^
- This type is deprecated and no longer has any effect. Use object-type instead.
+This type is deprecated and no longer has any effect. Use object-type instead.
.. _container-type:
container-type
^^^^^^^^^^^^^^
- The ``container-type`` node indicates that the given class is a container and
- must be handled using one of the conversion helpers provided by attribute **type**.
- It is a child of the :ref:`typesystem` node and may contain
- :ref:`conversion-rule` child nodes.
+The ``container-type`` node indicates that the given class is a container and
+must be handled using one of the conversion helpers provided by attribute **type**.
+It is a child of the :ref:`typesystem` node and may contain
+:ref:`conversion-rule` child nodes.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <container-type name="..."
- since="..."
- type ="..."
- opaque-containers ="..." />
- </typesystem>
+ <typesystem>
+ <container-type name="..."
+ since="..."
+ type ="..."
+ opaque-containers ="..." />
+ </typesystem>
+
+The **name** attribute is the fully qualified C++ class name. The **type**
+attribute is used to indicate what conversion rule will be applied to the
+container. It can be one of: *list*, *set*, *map*, *multi-map* or *pair*.
+
+Some types were deprecated in 6.2: *string-list*, *linked-list*, *vector*,
+*stack* and *queue* are equivalent to *list*. *hash* and *multi-hash*
+are equivalent to *map* and *multi-map*, respectively.
- The **name** attribute is the fully qualified C++ class name. The **type**
- attribute is used to indicate what conversion rule will be applied to the
- container. It can be one of: *list*, *set*, *map*, *multi-map* or *pair*.
+The *optional* **opaque-containers** attribute specifies a semi-colon separated
+list of mappings from instantiations to a type name for
+:ref:`opaque-containers`:
- Some types were deprecated in 6.2: *string-list*, *linked-list*, *vector*,
- *stack* and *queue* are equivalent to *list*. *hash* and *multi-hash*
- are equivalent to *map* and *multi-map*, respectively.
+.. code-block:: xml
+
+ <typesystem>
+ <container-type name="std::array"
+ opaque-containers ="int,3:IntArray3;float,4:FloatArray4">
+
+
+The *optional* **since** value is used to specify the API version of this container.
+
+Some common standard containers are :ref:`built-in <builtin-cpp-container-types>`,
+and there are also a number of useful
+:ref:`predefined conversion templates <predefined_templates>`.
+
+.. _opaque-container:
- The *optional* **opaque-containers** attribute specifies a semi-colon separated
- list of colon separated pairs of instantiation and name for
- :ref:`opaque-containers`.
+opaque-container
+^^^^^^^^^^^^^^^^
- The *optional* **since** value is used to specify the API version of this container.
+The ``opaque-container`` element can be used to add further instantiations
+of :ref:`opaque containers <opaque-containers>` to existing container types
+(built-in or specified by :ref:`container-type` in included modules).
+It is a child of the :ref:`typesystem` node.
- See :ref:`predefined_templates` for built-in templates for standard type
- conversion rules.
+.. code-block:: xml
+
+ <typesystem>
+ <oqaque-container name="..." opaque-containers ="..." />
+ </typesystem>
- Some common standard containers (``std::list``, ``std::vector``, ``std::pair``,
- ``std::map`` and ``std::unordered_map``) are built-in. They only need to be
- specified if :ref:`opaque-containers` should be generated.
+For the **name** and **opaque-containers** attributes,
+see :ref:`container-type`.
.. _typedef-type:
typedef-type
^^^^^^^^^^^^
- The ``typedef-type`` node allows for specifying typedefs in the typesystem. They
- are mostly equivalent to spelling out the typedef in the included header, which
- is often complicated when trying to wrap libraries whose source code cannot be
- easily extended.
- It is a child of the :ref:`typesystem` node or other type nodes.
+The ``typedef-type`` node allows for specifying typedefs in the typesystem. They
+are mostly equivalent to spelling out the typedef in the included header, which
+is often complicated when trying to wrap libraries whose source code cannot be
+easily extended.
+It is a child of the :ref:`typesystem` node or other type nodes.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <typedef-type name="..."
- source="..."
- since="..." />
- </typesystem>
+ <typesystem>
+ <typedef-type name="..."
+ source="..."
+ since="..." />
+ </typesystem>
- The **source** attribute is the source. Example:
+The **source** attribute is the source. Example:
- .. code-block:: xml
+.. code-block:: xml
- <namespace-type name='std'>
- <value-type name='optional' generate='no'/>\n"
- </namespace-type>
- <typedef-type name="IntOptional" source="std::optional&lt;int&gt;"/>
+ <namespace-type name='std'>
+ <value-type name='optional' generate='no'/>\n"
+ </namespace-type>
+ <typedef-type name="IntOptional" source="std::optional&lt;int&gt;"/>
- is equivalent to
+is equivalent to
- .. code-block:: c++
+.. code-block:: c++
- typedef std::optional<int> IntOptional;
+ typedef std::optional<int> IntOptional;
- The *optional* **since** value is used to specify the API version of this type.
+The *optional* **since** value is used to specify the API version of this type.
.. _custom-type:
custom-type
^^^^^^^^^^^
- The ``custom-type`` node simply makes the parser aware of the existence of a target
- language type, thus avoiding errors when trying to find a type used in function
- signatures and other places. The proper handling of the custom type is meant to
- be done by a generator using the APIExractor.
- It is a child of the :ref:`typesystem` node.
+The ``custom-type`` node simply makes the parser aware of the existence of a target
+language type, thus avoiding errors when trying to find a type used in function
+signatures and other places. The proper handling of the custom type is meant to
+be done by a generator using the APIExractor.
+It is a child of the :ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <custom-type name="..."
- check-function="..." />
- </typesystem>
+ <typesystem>
+ <custom-type name="..."
+ check-function="..." />
+ </typesystem>
- The **name** attribute is the name of the custom type, e.g., "PyObject".
+The **name** attribute is the name of the custom type, e.g., "PyObject".
- The *optional* **check-function** attribute can be used to specify a
- boolean check function that verifies if the PyObject is of the given type
- in the function overload decisor. While shiboken knows common check
- functions like ``PyLong_Check()`` or ``PyType_Check()``, it might be useful
- to provide one for function arguments modified to be custom types
- handled by injected code (see :ref:`replace-type`).
+The *optional* **check-function** attribute can be used to specify a
+boolean check function that verifies if the PyObject is of the given type
+in the function overload decisor. While shiboken knows common check
+functions like ``PyLong_Check()`` or ``PyType_Check()``, it might be useful
+to provide one for function arguments modified to be custom types
+handled by injected code (see :ref:`replace-type`).
- See :ref:`cpython-types` for built-in types.
+See :ref:`cpython-types` for built-in types.
.. _smart-pointer-type:
smart-pointer-type
^^^^^^^^^^^^^^^^^^
- The ``smart pointer`` type node indicates that the given class is a smart pointer
- and requires inserting calls to **getter** to access the pointeee.
- Currently, the usage is limited to function return values.
- **ref-count-method** specifies the name of the method used to do reference counting.
- It is a child of the :ref:`typesystem` node or other type nodes.
-
- The *optional* attribute **instantiations** specifies for which instantiations
- of the smart pointer wrappers will be generated (comma-separated list).
- By default, this will happen for all instantiations found by code parsing.
- This might be a problem when linking different modules, since wrappers for the
- same instantiation might be generated into different modules, which then clash.
- Providing an instantiations list makes it possible to specify which wrappers
- will be generated into specific modules.
-
- .. code-block:: xml
-
- <typesystem>
- <smart-pointer-type name="..."
- since="..."
- type="shared | handle | value-handle | unique"
- getter="..."
- ref-count-method="..."
- value-check-method="..."
- null-check-method="..."
- reset-method="..."
- instantiations="..."/>
- </typesystem>
-
-
- The *optional* attribute **value-check-method** specifies a method
- that can be used to check whether the pointer has a value.
-
- The *optional* attribute **null-check-method** specifies a method
- that can be used to check for ``nullptr``.
-
- The *optional* attribute **reset-method** specifies a method
- that can be used to clear the pointer.
-
- The *optional* attribute **type** specifies the type:
-
- *shared*
- A standard shared pointer.
- *handle*
- A basic pointer handle which has a getter function and an
- ``operator->``.
- *value-handle*
- A handle which has a getter function returning a value
- (``T`` instead of ``T *`` as for the other types).
- It can be used for ``std::optional``.
- *unique*
- A standard, unique pointer (``std::unique_ptr``) or a similar
- movable pointer.
- Specifying the ``reset-method`` attribute is required for this work.
-
- The example below shows an entry for a ``std::shared_ptr``:
-
- .. code-block:: xml
+The ``smart pointer`` type node indicates that the given class is a smart pointer
+and requires inserting calls to **getter** to access the pointeee.
+Currently, the usage is limited to function return values.
+**ref-count-method** specifies the name of the method used to do reference counting.
+It is a child of the :ref:`typesystem` node or other type nodes.
- <system-include file-name="memory"/>
+The *optional* attribute **instantiations** specifies for which instantiations
+of the smart pointer wrappers will be generated (comma-separated list).
+By default, this will happen for all instantiations found by code parsing.
+This might be a problem when linking different modules, since wrappers for the
+same instantiation might be generated into different modules, which then clash.
+Providing an instantiations list makes it possible to specify which wrappers
+will be generated into specific modules.
+
+.. code-block:: xml
+
+ <typesystem>
+ <smart-pointer-type name="..."
+ since="..."
+ type="shared | handle | value-handle | unique"
+ getter="..."
+ ref-count-method="..."
+ value-check-method="..."
+ null-check-method="..."
+ reset-method="..."
+ instantiations="..."/>
+ </typesystem>
+
+
+The *optional* attribute **value-check-method** specifies a method
+that can be used to check whether the pointer has a value.
- <namespace-type name="std">
+The *optional* attribute **null-check-method** specifies a method
+that can be used to check for ``nullptr``.
+
+The *optional* attribute **reset-method** specifies a method
+that can be used to clear the pointer.
+
+The *optional* instantiations attribute specifies a comma-separated
+list of instantiation types. When left empty, all instantiations
+found in the code will be generated. The type name might optionally
+be followed an equal sign and the Python type name, for example
+``instantiations="int=IntPtr,double=DoublePtr"``.
+It is also possible to specify a namespace delimited by ``::``.
+
+The *optional* attribute **type** specifies the type:
+
+*shared*
+ A standard shared pointer.
+*handle*
+ A basic pointer handle which has a getter function and an
+ ``operator->``.
+*value-handle*
+ A handle which has a getter function returning a value
+ (``T`` instead of ``T *`` as for the other types).
+ It can be used for ``std::optional``.
+*unique*
+ A standard, unique pointer (``std::unique_ptr``) or a similar
+ movable pointer.
+ Specifying the ``reset-method`` attribute is required for this work.
+
+The example below shows an entry for a ``std::shared_ptr``:
+
+.. code-block:: xml
+
+ <system-include file-name="memory"/>
+
+ <namespace-type name="std">
+ <include file-name="memory" location="global"/>
+ <modify-function signature="^.*$" remove="all"/>
+ <enum-type name="pointer_safety"/>
+ <smart-pointer-type name="shared_ptr" type="shared" getter="get"
+ ref-count-method="use_count"
+ instantiations="Integer">
+ <include file-name="memory" location="global"/>
+ </smart-pointer-type>
+ </namespace-type>
+
+If the smart pointer is the only relevant class from namespace ``std``,
+it can also be hidden:
+
+.. code-block:: xml
+
+ <namespace-type name="std" visible="no">
+ <smart-pointer-type name="shared_ptr" type="shared" getter="get"
+ ref-count-method="use_count"
+ instantiations="Integer">
<include file-name="memory" location="global"/>
- <modify-function signature="^.*$" remove="all"/>
- <enum-type name="pointer_safety"/>
- <smart-pointer-type name="shared_ptr" type="shared" getter="get"
- ref-count-method="use_count"
- instantiations="Integer">
- <include file-name="memory" location="global"/>
- </smart-pointer-type>
- </namespace-type>
-
- If the smart pointer is the only relevant class from namespace ``std``,
- it can also be hidden:
-
- .. code-block:: xml
-
- <namespace-type name="std" visible="no">
- <smart-pointer-type name="shared_ptr" type="shared" getter="get"
- ref-count-method="use_count"
- instantiations="Integer">
- <include file-name="memory" location="global"/>
- </smart-pointer-type>
- </namespace-type>
-
- First, shiboken is told to actually parse the system include files
- containing the class definition using the :ref:`system_include`
- element. For the ``namespace-type`` and ``smart-pointer-type``, the
- standard include files are given to override the internal implementation
- header ``shared_ptr.h``.
- This creates some wrapper sources which need to be added to the
- ``CMakeLists.txt`` of the module.
+ </smart-pointer-type>
+ </namespace-type>
+
+First, shiboken is told to actually parse the system include files
+containing the class definition using the :ref:`system_include`
+element. For the ``namespace-type`` and ``smart-pointer-type``, the
+standard include files are given to override the internal implementation
+header ``shared_ptr.h``.
+This creates some wrapper sources which need to be added to the
+``CMakeLists.txt`` of the module.
.. _function:
function
^^^^^^^^
- The ``function`` node indicates that the given C++ global function is mapped
- onto the target language. It is a child of the :ref:`typesystem` node
- and may contain a :ref:`modify-function` child node.
+The ``function`` node indicates that the given C++ global function is mapped
+onto the target language. It is a child of the :ref:`typesystem` node
+and may contain a :ref:`modify-function` child node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <function signature="..." rename="..." since="..." snake-case="yes | no | both" />
- </typesystem>
+ <typesystem>
+ <function signature="..." rename="..." since="..."
+ allow-thread="true | auto | false"
+ doc-file = "..."
+ exception-handling="off | auto-off | auto-on | on"
+ overload-number="number"
+ snake-case="yes | no | both" />
+ </typesystem>
+
+There is a limitation; you cannot add a function overload using
+the :ref:`add-function` tag to an existent function.
- There is a limitation; you cannot add a function overload using
- the :ref:`add-function` tag to an existent function.
+The *optional* **since** attribute is used to specify the API version in which
+the function was introduced.
- The *optional* **since** attribute is used to specify the API version in which
- the function was introduced.
+The *optional* **rename** attribute is used to modify the function name.
- The *optional* **rename** attribute is used to modify the function name.
+The *optional* **doc-file** attribute specifies the base name of the C++ or
+``.qdoc`` file indicated by ``\relates`` or ``\headerfile`` in ``qdoc``, to
+which the documentation of the function is to be added and displayed in the
+case its a global function. This attribute is for ``qdoc`` only.
- The *optional* **snake-case** attribute allows for overriding the value
- specified on the **typesystem** element.
+For the *optional* attributes **allow-thread**, **exception-handling**,
+**overload-number** and **snake-case**, see :ref:`modify-function`.
.. _system_include:
system-include
^^^^^^^^^^^^^^
- The optional **system-include** specifies the name of a system include
- file or a system include path (indicated by a trailing slash) to be
- parsed. Normally, include files considered to be system include
- files are skipped by the C++ code parser. Its primary use case
- is exposing classes from the STL library.
- It is a child of the :ref:`typesystem` node.
+The optional **system-include** specifies the name of a system include
+file or a system include path (indicated by a trailing slash) to be
+parsed. Normally, include files considered to be system include
+files are skipped by the C++ code parser. Its primary use case
+is exposing classes from the STL library.
+It is a child of the :ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <system-include file-name="memory"/>
- <system-include file-name="/usr/include/Qt/"/>
- </typesystem>
+ <typesystem>
+ <system-include file-name="memory"/>
+ <system-include file-name="/usr/include/Qt/"/>
+ </typesystem>
.. _conditional_processing:
Conditional Processing
^^^^^^^^^^^^^^^^^^^^^^
- Simple processing instructions are provided for including or excluding
- sections depending on the presence of keywords. The syntax is:
+Simple processing instructions are provided for including or excluding
+sections depending on the presence of keywords. The syntax is:
- .. code-block:: xml
+.. code-block:: xml
- <?if keyword !excluded_keyword ?>
- ...
- <?endif?>
+ <?if keyword !excluded_keyword ?>
+ ...
+ <?endif?>
- There are predefined keywords indicating the operating system (``windows``,
- ``unix`` and ``darwin``).
+There are predefined keywords indicating the operating system (``windows``,
+``unix`` and ``darwin``).
- The language level passed to the ``language-level`` command line option
- is reflected as ``c++11``, ``c++14``, ``c++17`` or ``c++20``.
+The language level passed to the ``language-level`` command line option
+is reflected as ``c++11``, ``c++14``, ``c++17`` or ``c++20``.
- The class names passed to the
- :ref:`--drop-type-entries <drop-type-entries>` command line option
- are also predefined, prefixed by ``no_``. This allows for example
- for enclosing added functions referring to those classes within
- ``<?if !no_ClassName?>``, ``<?endif?>``.
+The class names passed to the
+:ref:`--drop-type-entries <drop-type-entries>` command line option
+are also predefined, prefixed by ``no_``. This allows for example
+for enclosing added functions referring to those classes within
+``<?if !no_ClassName?>``, ``<?endif?>``.
- Other keywords can be specified using the
- :ref:`--keywords <conditional_keywords>` command line option.
+Other keywords can be specified using the
+:ref:`--keywords <conditional_keywords>` command line option.
.. _private_types:
@@ -783,10 +867,10 @@ Defining Entities
It is possible to define entities using a simple processing instruction:
- .. code-block:: xml
+.. code-block:: xml
- <?entity name value?>
- <text>&name;</text>
+ <?entity name value?>
+ <text>&name;</text>
This allows for defining function signatures depending on platform
in conjunction with :ref:`conditional_processing`.
diff --git a/sources/shiboken6/doc/typesystem_templates.rst b/sources/shiboken6/doc/typesystem_templates.rst
index 22056b596..c32eb97d1 100644
--- a/sources/shiboken6/doc/typesystem_templates.rst
+++ b/sources/shiboken6/doc/typesystem_templates.rst
@@ -8,52 +8,52 @@ Using Code Templates
template
^^^^^^^^
- The ``template`` node registers a template that can be used to avoid
- duplicate code when extending the generated code, and it is a child of the
- :ref:`typesystem` node.
+The ``template`` node registers a template that can be used to avoid
+duplicate code when extending the generated code, and it is a child of the
+:ref:`typesystem` node.
- .. code-block:: xml
+.. code-block:: xml
- <typesystem>
- <template name="my_template">
- // the code
- </template>
- </typesystem>
+ <typesystem>
+ <template name="my_template">
+ // the code
+ </template>
+ </typesystem>
- Use the ``insert-template`` node to insert the template code (identified
- by the template's ``name`` attribute) into the generated code base.
+Use the ``insert-template`` node to insert the template code (identified
+by the template's ``name`` attribute) into the generated code base.
.. _insert-template:
insert-template
^^^^^^^^^^^^^^^
- The ``insert-template`` node includes the code template identified by the
- name attribute, and it can be a child of the :ref:`inject-code`,
- :ref:`conversion-rule` or :ref:`template` nodes.
+The ``insert-template`` node includes the code template identified by the
+name attribute, and it can be a child of the :ref:`inject-code`,
+:ref:`conversion-rule` or :ref:`template` nodes.
- .. code-block:: xml
+.. code-block:: xml
- <inject-code class="target" position="beginning">
- <insert-template name="my_template" />
- </inject-code>
+ <inject-code class="target" position="beginning">
+ <insert-template name="my_template" />
+ </inject-code>
- Use the ``replace`` node to modify the template code.
+Use the ``replace`` node to modify the template code.
replace
^^^^^^^
- The ``replace`` node allows you to modify template code before inserting it into
- the generated code, and it can be a child of the :ref:`insert-template` node.
+The ``replace`` node allows you to modify template code before inserting it into
+the generated code, and it can be a child of the :ref:`insert-template` node.
- .. code-block:: xml
+.. code-block:: xml
- <insert-template name="my_template">
- <replace from="..." to="..." />
- </insert-template>
+ <insert-template name="my_template">
+ <replace from="..." to="..." />
+ </insert-template>
- This node will replace the attribute ``from`` with the value pointed by
- ``to``.
+This node will replace the attribute ``from`` with the value pointed by
+``to``.
.. _predefined_templates:
@@ -65,49 +65,54 @@ built into shiboken.
Templates for :ref:`primitive-type`:
- +---------------------------------------+--------------------------------+
- |Name | Description |
- +---------------------------------------+--------------------------------+
- | ``shiboken_conversion_pylong_to_cpp`` | Convert a PyLong to a C++ type |
- +---------------------------------------+--------------------------------+
++---------------------------------------+--------------------------------+
+|Name | Description |
++---------------------------------------+--------------------------------+
+| ``shiboken_conversion_pylong_to_cpp`` | Convert a PyLong to a C++ type |
++---------------------------------------+--------------------------------+
Templates for :ref:`container-type`:
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pysequence_to_cpppair`` | Convert a PySequence to a C++ pair (std::pair/QPair) |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_cpppair_to_pytuple`` | Convert a C++ pair (std::pair/QPair) to a PyTuple |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_cppsequence_to_pylist`` | Convert a C++ sequential container to a PyList |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_cppsequence_to_pyset`` | Convert a C++ sequential container to a PySet |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pyiterable_to_cppsequentialcontainer`` | Convert an iterable Python type to a C++ sequential container (STL/Qt) |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve`` | Convert an iterable Python type to a C++ sequential container supporting reserve() |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pyiterable_to_cppsetcontainer`` | Convert a PySequence to a set-type C++ container (std::set/QSet) |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_stdmap_to_pydict`` | Convert a std::map/std::unordered_map to a PyDict |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_qmap_to_pydict`` | Convert a QMap/QHash to a PyDict |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pydict_to_stdmap`` | Convert a PyDict to a std::map/std::unordered_map |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pydict_to_qmap`` | Convert a PyDict to a QMap/QHash |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_stdmultimap_to_pydict`` | Convert a std::multimap to a PyDict of value lists |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_qmultimap_to_pydict`` | Convert a QMultiMap to a PyDict of value lists |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_stdunorderedmultimap_to_pydict`` | Convert a std::unordered_multimap to a PyDict of value lists |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_qmultihash_to_pydict`` | Convert a QMultiHash to a PyDict of value lists |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pydict_to_stdmultimap`` | Convert a PyDict of value lists to std::multimap/std::unordered_multimap |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
- | ``shiboken_conversion_pydict_to_qmultihash`` | Convert a PyDict of value lists to QMultiMap/QMultiHash |
- +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+Some container types are :ref:`built-in <builtin-cpp-container-types>`.
+In case they need to explicitly specified, the following templates can be used:
+
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pysequence_to_cpppair`` | Convert a PySequence to a C++ pair (std::pair/QPair) |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_cpppair_to_pytuple`` | Convert a C++ pair (std::pair/QPair) to a PyTuple |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_cppsequence_to_pylist`` | Convert a C++ sequential container to a PyList |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_cppsequence_to_pyset`` | Convert a C++ sequential container to a PySet |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pyiterable_to_cppsequentialcontainer`` | Convert an iterable Python type to a C++ sequential container (STL/Qt) |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve`` | Convert an iterable Python type to a C++ sequential container supporting reserve() |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pyiterable_to_cpparray`` | Convert an iterable Python type to a fixed-size array (std::array, std::span) |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pyiterable_to_cppsetcontainer`` | Convert a PySequence to a set-type C++ container (std::set/QSet) |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_stdmap_to_pydict`` | Convert a std::map/std::unordered_map to a PyDict |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_qmap_to_pydict`` | Convert a QMap/QHash to a PyDict |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pydict_to_stdmap`` | Convert a PyDict to a std::map/std::unordered_map |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pydict_to_qmap`` | Convert a PyDict to a QMap/QHash |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_stdmultimap_to_pydict`` | Convert a std::multimap to a PyDict of value lists |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_qmultimap_to_pydict`` | Convert a QMultiMap to a PyDict of value lists |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_stdunorderedmultimap_to_pydict`` | Convert a std::unordered_multimap to a PyDict of value lists |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_qmultihash_to_pydict`` | Convert a QMultiHash to a PyDict of value lists |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pydict_to_stdmultimap`` | Convert a PyDict of value lists to std::multimap/std::unordered_multimap |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+| ``shiboken_conversion_pydict_to_qmultihash`` | Convert a PyDict of value lists to QMultiMap/QMultiHash |
++----------------------------------------------------------------------+------------------------------------------------------------------------------------+
An entry for the type ``std::list`` using these templates looks like:
@@ -126,9 +131,3 @@ An entry for the type ``std::list`` using these templates looks like:
</target-to-native>
</conversion-rule>
</container-type>
-
-.. note:: From version 6.3, we do not have to explicitly specify the
- `<container-type/>` for C++ containers ``std::list``\, ``std::vector``\,
- ``std::pair``\, ``std::map`` and ``std::unordered_map``\. They are
- now built-in. However, they still have to be added for opaque
- containers or when modifying the built-in behavior.
diff --git a/sources/shiboken6/doc/typesystem_variables.rst b/sources/shiboken6/doc/typesystem_variables.rst
index c6564513b..d40891b9b 100644
--- a/sources/shiboken6/doc/typesystem_variables.rst
+++ b/sources/shiboken6/doc/typesystem_variables.rst
@@ -20,32 +20,30 @@ Variables
.. _cpp_return_argument:
**%0**
-
Replaced by the C++ return variable of the Python method/function wrapper.
.. _arg_number:
**%<number>**
-
Replaced by the name of a C++ argument in the position indicated by ``<number>``.
The argument counting starts with ``%1``, since ``%0`` represents the return
variable name. If the number indicates a variable that was removed in the
type system description, but there is a default value for it, this value will
be used. Consider this example:
- .. code-block:: c++
+ .. code-block:: c++
- void argRemoval(int a0, int a1 = 123);
+ void argRemoval(int a0, int a1 = 123);
- .. code-block:: xml
+ .. code-block:: xml
- <modify-function signature="argRemoval(int, int)">
- <modify-argument index="2">
- <remove-argument/>
- </modify-argument>
- </modify-function>
+ <modify-function signature="argRemoval(int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the
value ``123``.
@@ -54,7 +52,6 @@ Variables
.. _argument_names:
**%ARGUMENT_NAMES**
-
Replaced by a comma separated list with the names of all C++ arguments that
were not removed on the type system description for the method/function. When
the removed argument has a default value (original or provided in the type
@@ -66,37 +63,36 @@ Variables
Take the following method and related type system description as an example:
- .. code-block:: c++
+ .. code-block:: c++
- void argRemoval(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 56);
+ void argRemoval(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 56);
- .. code-block:: xml
+ .. code-block:: xml
- <modify-function signature="argRemoval(int, Point, bool, Point, int)">
- <modify-argument index="2">
- <remove-argument/>
- <replace-default-expression with="Point(6, 9)"/>
- </modify-argument>
- <modify-argument index="4">
- <remove-argument/>
- </modify-argument>
- </modify-function>
+ <modify-function signature="argRemoval(int, Point, bool, Point, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <replace-default-expression with="Point(6, 9)"/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
As seen on the XML description, the function's ``a1`` and ``a3`` arguments
were removed. If any ``inject-code`` for this function uses ``%ARGUMENT_NAMES``
the resulting list will be the equivalent of using individual argument type
system variables this way:
- .. code-block:: c++
+ .. code-block:: c++
- %1, Point(6, 9), %3, Point(3, 4), %5
+ %1, Point(6, 9), %3, Point(3, 4), %5
.. _arg_type:
**%ARG#_TYPE**
-
Replaced by the type of a C++ argument in the position indicated by ``#``.
The argument counting starts with ``%1``, since ``%0`` represents the return
variable in other contexts, but ``%ARG0_TYPE`` will not translate to the
@@ -104,18 +100,18 @@ Variables
:ref:`%RETURN_TYPE <return_type>` variable.
Example:
- .. code-block:: c++
+ .. code-block:: c++
- void argRemoval(int a0, int a1 = 123);
+ void argRemoval(int a0, int a1 = 123);
- .. code-block:: xml
+ .. code-block:: xml
- <modify-function signature="argRemoval(int, int)">
- <modify-argument index="2">
- <remove-argument/>
- </modify-argument>
- </modify-function>
+ <modify-function signature="argRemoval(int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the
value ``123``.
@@ -124,40 +120,38 @@ Variables
.. _converttocpp:
**%CONVERTTOCPP[CPPTYPE]**
-
Replaced by a |project| conversion call that converts a Python variable
to a C++ variable of the type indicated by ``CPPTYPE``.
- Typically, this is a variable assignment:
+ Typically, this is a variable assignment:
- .. code-block:: c++
+ .. code-block:: c++
- double value = %CONVERTTOCPP[double](pyValue);
+ double value = %CONVERTTOCPP[double](pyValue);
- Pointer assignments are also possible:
+ Pointer assignments are also possible:
- .. code-block:: c++
+ .. code-block:: c++
- void f(double *valuePtr)
- {
- *valuePtr = %CONVERTTOCPP[double](pyValue);
+ void f(double *valuePtr)
+ {
+ *valuePtr = %CONVERTTOCPP[double](pyValue);
- Note however, that for variable definitions, the type must
- be a space-delimited token:
+ Note however, that for variable definitions, the type must
+ be a space-delimited token:
- .. code-block:: c++
+ .. code-block:: c++
- double * valuePtr = %CONVERTTOCPP[double](pyValue);
+ double * valuePtr = %CONVERTTOCPP[double](pyValue);
- since it otherwise would be indistinguishable from the pointer assignment
- above.
+ since it otherwise would be indistinguishable from the pointer assignment
+ above.
- It is possible to use "auto" as type.
+ It is possible to use "auto" as type.
.. _converttopython:
**%CONVERTTOPYTHON[CPPTYPE]**
-
Replaced by a |project| conversion call that converts a C++ variable of the
type indicated by ``CPPTYPE`` to the proper Python object.
@@ -165,7 +159,6 @@ Variables
.. _isconvertible:
**%ISCONVERTIBLE[CPPTYPE]**
-
Replaced by a |project| "isConvertible" call that checks if a Python
variable is convertible (via an implicit conversion or cast operator call)
to a C++ variable of the type indicated by ``CPPTYPE``.
@@ -174,7 +167,6 @@ Variables
.. _checktype:
**%CHECKTYPE[CPPTYPE]**
-
Replaced by a |project| "checkType" call that verifies if a Python
if of the type indicated by ``CPPTYPE``.
@@ -182,14 +174,12 @@ Variables
.. _cppself:
**%CPPSELF**
-
Replaced by the wrapped C++ object instance that owns the method in which the
code with this variable was inserted.
.. _cpptype:
**%CPPTYPE**
-
Replaced by the original name of the C++ class, without any namespace prefix,
that owns the method in which the code with this variable was inserted. It will
work on class level code injections also. Notice that ``CPPTYPE`` differs from
@@ -202,22 +192,18 @@ Variables
.. _function_name:
**%FUNCTION_NAME**
-
Replaced by the name of a function or method.
-
.. _py_return_argument:
**%PYARG_0**
-
Replaced by the name of the Python return variable of the Python method/function wrapper.
.. _pyarg:
**%PYARG_<number>**
-
Similar to ``%<number>``, but is replaced by the Python arguments (PyObjects)
received by the Python wrapper method.
@@ -228,16 +214,16 @@ Variables
The example
- .. code-block:: c++
+ .. code-block:: c++
- long a = PyLong_AS_LONG(%PYARG_1);
+ long a = PyLong_AS_LONG(%PYARG_1);
is equivalent of
- .. code-block:: c++
+ .. code-block:: c++
- long a = PyLong_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0));
+ long a = PyLong_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0));
The generator tries to be smart with attributions, but it will work for the
@@ -245,24 +231,23 @@ Variables
This example
- .. code-block:: c++
+ .. code-block:: c++
- Py_DECREF(%PYARG_1);
- %PYARG_1 = PyLong_FromLong(10);
+ Py_DECREF(%PYARG_1);
+ %PYARG_1 = PyLong_FromLong(10);
is equivalent of
- .. code-block:: c++
+ .. code-block:: c++
- Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0));
- PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyLong_FromLong(10));
+ Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0));
+ PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyLong_FromLong(10));
.. _pyself:
**%PYSELF**
-
Replaced by the Python wrapper variable (a PyObject) representing the instance
bounded to the Python wrapper method which receives the custom code.
@@ -270,7 +255,6 @@ Variables
.. _python_arguments:
**%PYTHON_ARGUMENTS**
-
Replaced by the pointer to the Python tuple with Python objects converted from
the C++ arguments received on the binding override of a virtual method.
This tuple is the same passed as arguments to the Python method overriding the
@@ -280,7 +264,6 @@ Variables
.. _python_method_override:
**%PYTHON_METHOD_OVERRIDE**
-
This variable is used only on :ref:`native method code injections
<codeinjecting_method_native>`, i.e. on the binding overrides for C++ virtual
methods. It is replaced by a pointer to the Python method override.
@@ -289,7 +272,6 @@ Variables
.. _pythontypeobject:
**%PYTHONTYPEOBJECT**
-
Replaced by the Python type object for the context in which it is inserted:
method or class modification.
@@ -297,7 +279,6 @@ Variables
.. _beginallowthreads:
**%BEGIN_ALLOW_THREADS**
-
Replaced by a thread state saving procedure.
Must match with a :ref:`%END_ALLOW_THREADS <endallowthreads>` variable.
@@ -305,7 +286,6 @@ Variables
.. _endallowthreads:
**%END_ALLOW_THREADS**
-
Replaced by a thread state restoring procedure.
Must match with a :ref:`%BEGIN_ALLOW_THREADS <beginallowthreads>` variable.
@@ -313,14 +293,12 @@ Variables
.. _return_type:
**%RETURN_TYPE**
-
Replaced by the type returned by a function or method.
.. _type:
**%TYPE**
-
Replaced by the name of the class to which a function belongs. May be used
in code injected at method or class level.
@@ -335,27 +313,27 @@ sections, below is an excerpt from the type system description of a |project|
test. It changes a method that received ``argc/argv`` arguments into something
that expects a Python sequence instead.
- .. code-block:: xml
-
- <modify-function signature="overloadedMethod(int, char**)">
- <modify-argument index="1">
- <replace-type modified-type="PySequence" />
- </modify-argument>
- <modify-argument index="2">
- <remove-argument />
- </modify-argument>
- <inject-code class="target" position="beginning">
- int argc;
- char** argv;
- if (!PySequence_to_argc_argv(%PYARG_1, &amp;argc, &amp;argv)) {
- PyErr_SetString(PyExc_TypeError, "error");
- return 0;
- }
- %RETURN_TYPE foo = %CPPSELF.%FUNCTION_NAME(argc, argv);
- %0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo);
-
- for (int i = 0; i &lt; argc; ++i)
- delete[] argv[i];
- delete[] argv;
- </inject-code>
- </modify-function>
+.. code-block:: xml
+
+ <modify-function signature="overloadedMethod(int, char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int argc;
+ char** argv;
+ if (!PySequence_to_argc_argv(%PYARG_1, &amp;argc, &amp;argv)) {
+ PyErr_SetString(PyExc_TypeError, "error");
+ return 0;
+ }
+ %RETURN_TYPE foo = %CPPSELF.%FUNCTION_NAME(argc, argv);
+ %0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo);
+
+ for (int i = 0; i &lt; argc; ++i)
+ delete[] argv[i];
+ delete[] argv;
+ </inject-code>
+ </modify-function>
diff --git a/sources/shiboken6/generator/CMakeLists.txt b/sources/shiboken6/generator/CMakeLists.txt
index 276661ab9..aebe2cd5e 100644
--- a/sources/shiboken6/generator/CMakeLists.txt
+++ b/sources/shiboken6/generator/CMakeLists.txt
@@ -1,24 +1,46 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(shibokengenerator)
set(package_name "Shiboken6Tools")
-if(NOT (Qt${QT_MAJOR_VERSION}Core_FOUND AND PYTHONINTERP_FOUND))
+set(CMAKE_AUTOMOC ON)
+
+if(NOT (Qt${QT_MAJOR_VERSION}Core_FOUND AND Python_Interpreter_FOUND))
message(WARNING "Some dependencies were not found: shiboken6 generator compilation disabled!")
return()
endif()
set(shiboken6_SRC
-generator.cpp
-shiboken/cppgenerator.cpp
-shiboken/cppgenerator_container.cpp
-shiboken/headergenerator.cpp
-shiboken/overloaddata.cpp
-shiboken/shibokengenerator.cpp
+defaultvalue.cpp defaultvalue.h
+generator.cpp generator.h
+generatorcontext.cpp generatorcontext.h
main.cpp
+shiboken/configurablescope.h
+shiboken/cppgenerator.cpp shiboken/cppgenerator.h
+shiboken/cppgenerator_container.cpp
+shiboken/cppgenerator_smartpointer.cpp
+shiboken/ctypenames.h
+shiboken/generatorargument.cpp shiboken/generatorargument.h shiboken/generatorstrings.h
+shiboken/headergenerator.cpp shiboken/headergenerator.h
+shiboken/overloaddata.cpp shiboken/overloaddata.h
+shiboken/pytypenames.h
+shiboken/shibokengenerator.cpp shiboken/shibokengenerator.h
)
+find_libclang()
+
+if(${STANDALONE})
+ list(APPEND CMAKE_INSTALL_RPATH ${base}/Qt/lib)
+else()
+ list(APPEND CMAKE_INSTALL_RPATH ${QT6_INSTALL_PREFIX}/${QT6_INSTALL_LIBS}
+ ${libclang_lib_dir})
+endif()
+
add_executable(shiboken6 ${shiboken6_SRC})
add_executable(Shiboken6::shiboken6 ALIAS shiboken6)
add_dependencies(shiboken6 apiextractor)
+
set_target_properties(shiboken6 PROPERTIES OUTPUT_NAME shiboken6${shiboken6_SUFFIX})
target_include_directories(shiboken6 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/shiboken
@@ -27,9 +49,13 @@ target_include_directories(shiboken6 PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${apiextractor_SOURCE_DIR}
)
-target_link_libraries(shiboken6 apiextractor Qt${QT_MAJOR_VERSION}::Core)
+target_link_libraries(shiboken6 apiextractor Qt::Core)
if (NOT DISABLE_DOCSTRINGS)
- target_sources(shiboken6 PRIVATE qtdoc/qtxmltosphinx.cpp qtdoc/qtdocgenerator.cpp)
+ target_sources(shiboken6 PRIVATE
+ qtdoc/qtdocgenerator.cpp qtdoc/qtdocgenerator.h
+ qtdoc/qtxmltosphinx.cpp qtdoc/qtxmltosphinx.h
+ qtdoc/qtxmltosphinxinterface.h
+ qtdoc/rstformat.h)
target_compile_definitions(shiboken6 PUBLIC DOCSTRINGS_ENABLED QT_LEAN_HEADERS=1)
endif()
diff --git a/sources/shiboken6/generator/_config.py.in b/sources/shiboken6/generator/_config.py.in
index 985735fa4..ed7e67098 100644
--- a/sources/shiboken6/generator/_config.py.in
+++ b/sources/shiboken6/generator/_config.py.in
@@ -7,3 +7,4 @@ version_info = (@shiboken_MAJOR_VERSION@, @shiboken_MINOR_VERSION@, @shiboken_MI
@PACKAGE_BUILD_COMMIT_HASH_DESCRIBED@
@PACKAGE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT@
@PACKAGE_SETUP_PY_PACKAGE_VERSION_ASSIGNMENT@
+@QT_MACOS_DEPLOYMENT_TARGET@
diff --git a/sources/shiboken6/generator/defaultvalue.cpp b/sources/shiboken6/generator/defaultvalue.cpp
new file mode 100644
index 000000000..89cc9fa77
--- /dev/null
+++ b/sources/shiboken6/generator/defaultvalue.cpp
@@ -0,0 +1,120 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "defaultvalue.h"
+
+#include "qtcompat.h"
+
+#include <QtCore/QDebug>
+
+using namespace Qt::StringLiterals;
+
+// DefaultValue is used for storing default values of types for which code is
+// generated in different contexts:
+//
+// Context | Example: "Class *" | Example: "Class" with default Constructor
+// --------------------+-------------------------------+------------------------------------------
+// Variable | var{nullptr}; | var;
+// initializations | |
+// --------------------+-------------------------------+------------------------------------------
+// Return values | return nullptr; | return {}
+// --------------------+-------------------------------+------------------------------------------
+// constructor | static_cast<Class *>(nullptr) | Class()
+// arguments lists | |
+// (recursive, precise | |
+// matching). | |
+
+DefaultValue::DefaultValue(Type t, QString value) :
+ m_type(t), m_value(std::move(value))
+{
+}
+
+DefaultValue::DefaultValue(QString customValue) :
+ m_type(Custom), m_value(std::move(customValue))
+{
+}
+
+QString DefaultValue::returnValue() const
+{
+ switch (m_type) {
+ case DefaultValue::Boolean:
+ return u"false"_s;
+ case DefaultValue::CppScalar:
+ return u"0"_s;
+ case DefaultValue::Custom:
+ case DefaultValue::Enum:
+ return m_value;
+ case DefaultValue::Pointer:
+ return u"nullptr"_s;
+ case DefaultValue::Void:
+ return {};
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ return m_value + u"()"_s;
+ case DefaultValue::DefaultConstructor:
+ break;
+ }
+ return u"{}"_s;
+}
+
+QString DefaultValue::initialization() const
+{
+ switch (m_type) {
+ case DefaultValue::Boolean:
+ return u"{false}"_s;
+ case DefaultValue::CppScalar:
+ return u"{0}"_s;
+ case DefaultValue::Custom:
+ return u" = "_s + m_value;
+ case DefaultValue::Enum:
+ return u'{' + m_value + u'}';
+ case DefaultValue::Pointer:
+ return u"{nullptr}"_s;
+ case DefaultValue::Void:
+ Q_ASSERT(false);
+ break;
+ case DefaultValue::DefaultConstructor:
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ break;
+ }
+ return {};
+}
+
+QString DefaultValue::constructorParameter() const
+{
+ switch (m_type) {
+ case DefaultValue::Boolean:
+ return u"false"_s;
+ case DefaultValue::CppScalar: {
+ // PYSIDE-846: Use static_cast in case of "unsigned long" and similar
+ const QString cast = m_value.contains(u' ')
+ ? u"static_cast<"_s + m_value + u'>'
+ : m_value;
+ return cast + u"(0)"_s;
+ }
+ case DefaultValue::Custom:
+ case DefaultValue::Enum:
+ return m_value;
+ case DefaultValue::Pointer:
+ // Be precise here to be able to differentiate between constructors
+ // taking different pointer types, cf
+ // QTreeWidgetItemIterator(QTreeWidget *) and
+ // QTreeWidgetItemIterator(QTreeWidgetItemIterator *).
+ return u"static_cast<"_s + m_value + u"*>(nullptr)"_s;
+ case DefaultValue::Void:
+ Q_ASSERT(false);
+ break;
+ case DefaultValue::DefaultConstructor:
+ case DefaultValue::DefaultConstructorWithDefaultValues:
+ break;
+ }
+ return m_value + u"()"_s;
+}
+
+QDebug operator<<(QDebug debug, const DefaultValue &v)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "DefaultValue(" << v.type() << ", \"" << v.value() << "\")";
+ return debug;
+}
diff --git a/sources/shiboken6/generator/defaultvalue.h b/sources/shiboken6/generator/defaultvalue.h
new file mode 100644
index 000000000..d518d134f
--- /dev/null
+++ b/sources/shiboken6/generator/defaultvalue.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef DEFAULTVALUE_H
+#define DEFAULTVALUE_H
+
+#include <QtCore/QString>
+
+QT_FORWARD_DECLARE_CLASS(QDebug);
+
+class DefaultValue
+{
+public:
+ enum Type
+ {
+ Boolean,
+ CppScalar, // A C++ scalar type (int,..) specified by value()
+ Custom, // A custom constructor/expression, uses value() as is
+ DefaultConstructor, // For classes named value()
+ DefaultConstructorWithDefaultValues, // as DefaultConstructor, but can't return {} though.
+ Enum, // Enum value as specified by value()
+ Pointer, // Pointer of type value()
+ Void // "", for return values only
+ };
+
+ explicit DefaultValue(Type t, QString value = QString());
+ explicit DefaultValue(QString customValue);
+
+ QString returnValue() const;
+ QString initialization() const;
+ QString constructorParameter() const;
+
+ QString value() const { return m_value; }
+ void setValue(const QString &value) { m_value = value; }
+
+ Type type() const { return m_type; }
+ void setType(Type type) { m_type = type; }
+
+private:
+ Type m_type;
+ QString m_value;
+};
+
+QDebug operator<<(QDebug debug, const DefaultValue &v);
+
+#endif // DEFAULTVALUE_H
diff --git a/sources/shiboken6/generator/generator.cpp b/sources/shiboken6/generator/generator.cpp
index b4d6cfab5..b224858c5 100644
--- a/sources/shiboken6/generator/generator.cpp
+++ b/sources/shiboken6/generator/generator.cpp
@@ -2,15 +2,17 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "generator.h"
+#include "defaultvalue.h"
+#include "generatorcontext.h"
#include "apiextractorresult.h"
-#include "ctypenames.h"
+#include "abstractmetaargument.h"
+#include "abstractmetaenum.h"
#include "abstractmetafunction.h"
#include "abstractmetalang.h"
-#include "parser/codemodel.h"
#include "messages.h"
+#include <optionsparser.h>
#include "reporthandler.h"
#include "fileout.h"
-#include "apiextractor.h"
#include "arraytypeentry.h"
#include "enumtypeentry.h"
#include "enumvaluetypeentry.h"
@@ -28,152 +30,14 @@
using namespace Qt::StringLiterals;
-static const char ENABLE_PYSIDE_EXTENSIONS[] = "enable-pyside-extensions";
-static const char AVOID_PROTECTED_HACK[] = "avoid-protected-hack";
-
-/**
- * DefaultValue is used for storing default values of types for which code is
- * generated in different contexts:
- *
- * Context | Example: "Class *" | Example: "Class" with default Constructor
- * --------------------+-------------------------------+------------------------------------------
- * Variable | var{nullptr}; | var;
- * initializations | |
- * --------------------+-------------------------------+------------------------------------------
- * Return values | return nullptr; | return {}
- * --------------------+-------------------------------+------------------------------------------
- * constructor | static_cast<Class *>(nullptr) | Class()
- * arguments lists | |
- * (recursive, precise | |
- * matching). | |
- */
-
-DefaultValue::DefaultValue(Type t, QString value) :
- m_type(t), m_value(std::move(value))
-{
-}
-
-DefaultValue::DefaultValue(QString customValue) :
- m_type(Custom), m_value(std::move(customValue))
-{
-}
-
-QString DefaultValue::returnValue() const
-{
- switch (m_type) {
- case DefaultValue::Boolean:
- return u"false"_s;
- case DefaultValue::CppScalar:
- return u"0"_s;
- case DefaultValue::Custom:
- case DefaultValue::Enum:
- return m_value;
- case DefaultValue::Pointer:
- return u"nullptr"_s;
- case DefaultValue::Void:
- return QString();
- case DefaultValue::DefaultConstructorWithDefaultValues:
- return m_value + u"()"_s;
- case DefaultValue::DefaultConstructor:
- break;
- }
- return u"{}"_s;
-}
-
-QString DefaultValue::initialization() const
-{
- switch (m_type) {
- case DefaultValue::Boolean:
- return u"{false}"_s;
- case DefaultValue::CppScalar:
- return u"{0}"_s;
- case DefaultValue::Custom:
- return u" = "_s + m_value;
- case DefaultValue::Enum:
- return u'{' + m_value + u'}';
- case DefaultValue::Pointer:
- return u"{nullptr}"_s;
- case DefaultValue::Void:
- Q_ASSERT(false);
- break;
- case DefaultValue::DefaultConstructor:
- case DefaultValue::DefaultConstructorWithDefaultValues:
- break;
- }
- return QString();
-}
-
-QString DefaultValue::constructorParameter() const
-{
- switch (m_type) {
- case DefaultValue::Boolean:
- return u"false"_s;
- case DefaultValue::CppScalar: {
- // PYSIDE-846: Use static_cast in case of "unsigned long" and similar
- const QString cast = m_value.contains(u' ')
- ? u"static_cast<"_s + m_value + u'>'
- : m_value;
- return cast + u"(0)"_s;
- }
- case DefaultValue::Custom:
- case DefaultValue::Enum:
- return m_value;
- case DefaultValue::Pointer:
- // Be precise here to be able to differentiate between constructors
- // taking different pointer types, cf
- // QTreeWidgetItemIterator(QTreeWidget *) and
- // QTreeWidgetItemIterator(QTreeWidgetItemIterator *).
- return u"static_cast<"_s + m_value + u"*>(nullptr)"_s;
- case DefaultValue::Void:
- Q_ASSERT(false);
- break;
- case DefaultValue::DefaultConstructor:
- case DefaultValue::DefaultConstructorWithDefaultValues:
- break;
- }
- return m_value + u"()"_s;
-}
+static constexpr auto ENABLE_PYSIDE_EXTENSIONS = "enable-pyside-extensions"_L1;
+static constexpr auto AVOID_PROTECTED_HACK = "avoid-protected-hack"_L1;
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const DefaultValue &v)
+struct GeneratorOptions
{
- QDebugStateSaver saver(debug);
- debug.noquote();
- debug.nospace();
- debug << "DefaultValue(" << v.type() << ", \"" << v.value() << "\")";
- return debug;
-}
-
-QDebug operator<<(QDebug debug, const GeneratorContext &c)
-{
- QDebugStateSaver saver(debug);
- debug.noquote();
- debug.nospace();
- debug << "GeneratorContext(\"" << c.metaClass()->name() << "\" ";
- if (c.useWrapper())
- debug << "[wrapper]";
- else if (c.forSmartPointer())
- debug << "[smart pointer] \"" << c.preciseType().cppSignature() << '"';
- else
- debug << "[class]";
- debug << ')';
- return debug;
-}
-
-#endif // !QT_NO_DEBUG_STREAM
-
-QString GeneratorContext::wrapperName() const
-{
- Q_ASSERT(m_type == WrappedClass);
- return m_wrappername;
-}
-
-QString GeneratorContext::effectiveClassName() const
-{
- if (m_type == SmartPointer)
- return m_preciseClassType.cppSignature();
- return m_type == WrappedClass ? m_wrappername : m_metaClass->qualifiedCppName();
-}
+ bool usePySideExtensions = false;
+ bool avoidProtectedHack = false;
+};
struct Generator::GeneratorPrivate
{
@@ -183,10 +47,14 @@ struct Generator::GeneratorPrivate
QString licenseComment;
AbstractMetaClassCList m_invisibleTopNamespaces;
bool m_hasPrivateClasses = false;
- bool m_usePySideExtensions = false;
- bool m_avoidProtectedHack = false;
+ static GeneratorOptions m_options;
};
+GeneratorOptions Generator::GeneratorPrivate::m_options;
+
+// Kept as a variable for a potential Qt-in-namespace support
+QString Generator::m_gsp = "::"_L1;
+
Generator::Generator() : m_d(new GeneratorPrivate)
{
}
@@ -209,10 +77,10 @@ bool Generator::setup(const ApiExtractorResult &api)
return false;
}
- for (auto c : api.classes()) {
+ for (const auto &c : api.classes()) {
if (c->enclosingClass() == nullptr && c->isInvisibleNamespace()) {
m_d->m_invisibleTopNamespaces.append(c);
- c->invisibleNamespaceRecursion([&](const AbstractMetaClass *ic) {
+ c->invisibleNamespaceRecursion([&](const AbstractMetaClassCPtr &ic) {
m_d->m_invisibleTopNamespaces.append(ic);
});
}
@@ -221,33 +89,51 @@ bool Generator::setup(const ApiExtractorResult &api)
return doSetup();
}
-Generator::OptionDescriptions Generator::options() const
+QList<OptionDescription> Generator::options()
{
return {
- {QLatin1StringView(AVOID_PROTECTED_HACK),
+ {AVOID_PROTECTED_HACK,
u"Avoid the use of the '#define protected public' hack."_s},
- {QLatin1StringView(ENABLE_PYSIDE_EXTENSIONS),
+ {ENABLE_PYSIDE_EXTENSIONS,
u"Enable PySide extensions, such as support for signal/slots,\n"
"use this if you are creating a binding for a Qt-based library."_s}
};
}
-bool Generator::handleOption(const QString & key, const QString & /* value */)
+class GeneratorOptionsParser : public OptionsParser
{
- if (key == QLatin1StringView(ENABLE_PYSIDE_EXTENSIONS))
- return ( m_d->m_usePySideExtensions = true);
- if (key == QLatin1StringView(AVOID_PROTECTED_HACK))
- return (m_d->m_avoidProtectedHack = true);
+public:
+ explicit GeneratorOptionsParser(GeneratorOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+
+private:
+ GeneratorOptions *m_options;
+};
+
+bool GeneratorOptionsParser::handleBoolOption(const QString & key, OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
+ if (key == ENABLE_PYSIDE_EXTENSIONS)
+ return ( m_options->usePySideExtensions = true);
+ if (key == AVOID_PROTECTED_HACK)
+ return ( m_options->avoidProtectedHack = true);
return false;
}
+std::shared_ptr<OptionsParser> Generator::createOptionsParser()
+{
+ return std::make_shared<GeneratorOptionsParser>(&GeneratorPrivate::m_options);
+}
+
QString Generator::fileNameForContextHelper(const GeneratorContext &context,
const QString &suffix,
FileNameFlags flags)
{
if (!context.forSmartPointer()) {
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
QString fileNameBase = flags.testFlag(FileNameFlag::UnqualifiedName)
? metaClass->name() : metaClass->qualifiedCppName();
if (!flags.testFlag(FileNameFlag::KeepCase))
@@ -269,12 +155,12 @@ const AbstractMetaClassCList &Generator::invisibleTopNamespaces() const
return m_d->m_invisibleTopNamespaces;
}
-PrimitiveTypeEntryList Generator::primitiveTypes()
+PrimitiveTypeEntryCList Generator::primitiveTypes()
{
return TypeDatabase::instance()->primitiveTypes();
}
-ContainerTypeEntryList Generator::containerTypes()
+ContainerTypeEntryCList Generator::containerTypes()
{
return TypeDatabase::instance()->containerTypes();
}
@@ -319,8 +205,8 @@ void Generator::setOutputDirectory(const QString &outDir)
bool Generator::generateFileForContext(const GeneratorContext &context)
{
- const AbstractMetaClass *cls = context.metaClass();
- auto *typeEntry = cls->typeEntry();
+ const auto cls = context.metaClass();
+ auto typeEntry = cls->typeEntry();
if (!shouldGenerate(typeEntry))
return true;
@@ -352,16 +238,17 @@ QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType &smartP
return fileName;
}
-GeneratorContext Generator::contextForClass(const AbstractMetaClass *c) const
+GeneratorContext Generator::contextForClass(const AbstractMetaClassCPtr &c) const
{
GeneratorContext result;
result.m_metaClass = c;
return result;
}
-GeneratorContext Generator::contextForSmartPointer(const AbstractMetaClass *c,
- const AbstractMetaType &t,
- const AbstractMetaClass *pointeeClass)
+GeneratorContext
+ Generator::contextForSmartPointer(const AbstractMetaClassCPtr &c,
+ const AbstractMetaType &t,
+ const AbstractMetaClassCPtr &pointeeClass)
{
GeneratorContext result;
result.m_metaClass = c;
@@ -373,17 +260,17 @@ GeneratorContext Generator::contextForSmartPointer(const AbstractMetaClass *c,
bool Generator::generate()
{
- for (auto cls : m_d->api.classes()) {
+ for (const auto &cls : m_d->api.classes()) {
if (!generateFileForContext(contextForClass(cls)))
return false;
- auto *te = cls->typeEntry();
+ auto te = cls->typeEntry();
if (shouldGenerate(te) && te->isPrivate())
m_d->m_hasPrivateClasses = true;
}
for (const auto &smp: m_d->api.instantiatedSmartPointers()) {
- const AbstractMetaClass *pointeeClass = nullptr;
- const auto *instantiatedType = smp.type.instantiations().constFirst().typeEntry();
+ AbstractMetaClassCPtr pointeeClass;
+ const auto instantiatedType = smp.type.instantiations().constFirst().typeEntry();
if (instantiatedType->isComplex()) // not a C++ primitive
pointeeClass = AbstractMetaClass::findClass(m_d->api.classes(), instantiatedType);
if (!generateFileForContext(contextForSmartPointer(smp.specialized, smp.type,
@@ -394,7 +281,7 @@ bool Generator::generate()
return finishGeneration();
}
-bool Generator::shouldGenerate(const TypeEntry *typeEntry) const
+bool Generator::shouldGenerate(const TypeEntryCPtr &typeEntry) const
{
return typeEntry->shouldGenerate();
}
@@ -409,24 +296,22 @@ bool Generator::hasPrivateClasses() const
return m_d->m_hasPrivateClasses;
}
-bool Generator::usePySideExtensions() const
+bool Generator::usePySideExtensions()
{
- return m_d->m_usePySideExtensions;
+ return GeneratorPrivate::m_options.usePySideExtensions;
}
-bool Generator::avoidProtectedHack() const
+bool Generator::avoidProtectedHack()
{
- return m_d->m_avoidProtectedHack;
+ return GeneratorPrivate::m_options.avoidProtectedHack;
}
-QString Generator::getFullTypeName(const TypeEntry *type)
+QString Generator::getFullTypeName(TypeEntryCPtr type)
{
QString result = type->qualifiedCppName();
if (type->isArray())
- type = static_cast<const ArrayTypeEntry *>(type)->nestedTypeEntry();
- if (!type->isCppPrimitive())
- result.prepend(u"::"_s);
- return result;
+ type = std::static_pointer_cast<const ArrayTypeEntry>(type)->nestedTypeEntry();
+ return isCppPrimitive(type) ? result : addGlobalScopePrefix(result);
}
QString Generator::getFullTypeName(const AbstractMetaType &type)
@@ -436,7 +321,7 @@ QString Generator::getFullTypeName(const AbstractMetaType &type)
if (type.isVoidPointer())
return u"void*"_s;
if (type.typeEntry()->isContainer())
- return u"::"_s + type.cppSignature();
+ return addGlobalScopePrefix(type.cppSignature());
QString typeName;
if (type.typeEntry()->isComplex() && type.hasInstantiations())
typeName = getFullTypeNameWithoutModifiers(type);
@@ -445,9 +330,11 @@ QString Generator::getFullTypeName(const AbstractMetaType &type)
return typeName + QString::fromLatin1("*").repeated(type.indirections());
}
-QString Generator::getFullTypeName(const AbstractMetaClass *metaClass)
+QString Generator::getFullTypeName(const AbstractMetaClassCPtr &metaClass)
{
- return u"::"_s + metaClass->qualifiedCppName();
+ const QString &qualName = metaClass->qualifiedCppName();
+ // Typedefs are generated into the global namespace
+ return metaClass->isTypeDef() ? qualName : addGlobalScopePrefix(qualName);
}
QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType &type)
@@ -473,7 +360,7 @@ QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType &type)
}
while (typeName.endsWith(u'*') || typeName.endsWith(u' '))
typeName.chop(1);
- return u"::"_s + typeName;
+ return addGlobalScopePrefix(typeName);
}
std::optional<DefaultValue>
@@ -502,13 +389,13 @@ std::optional<DefaultValue>
if (type.isNativePointer())
return DefaultValue(DefaultValue::Pointer, type.typeEntry()->qualifiedCppName());
if (type.isPointer())
- return DefaultValue(DefaultValue::Pointer, u"::"_s + type.typeEntry()->qualifiedCppName());
+ return DefaultValue(DefaultValue::Pointer, getFullTypeName(type.typeEntry()));
if (type.typeEntry()->isSmartPointer())
return minimalConstructor(api, type.typeEntry());
if (type.typeEntry()->isComplex()) {
- auto cType = static_cast<const ComplexTypeEntry *>(type.typeEntry());
+ auto cType = std::static_pointer_cast<const ComplexTypeEntry>(type.typeEntry());
if (cType->hasDefaultConstructor())
return DefaultValue(DefaultValue::Custom, cType->defaultConstructor());
auto klass = AbstractMetaClass::findClass(api.classes(), cType);
@@ -533,13 +420,13 @@ std::optional<DefaultValue>
std::optional<DefaultValue>
Generator::minimalConstructor(const ApiExtractorResult &api,
- const TypeEntry *type,
+ const TypeEntryCPtr &type,
QString *errorString)
{
if (!type)
return {};
- if (type->isCppPrimitive()) {
+ if (isCppPrimitive(type)) {
const QString &name = type->qualifiedCppName();
return name == u"bool"
? DefaultValue(DefaultValue::Boolean)
@@ -547,12 +434,11 @@ std::optional<DefaultValue>
}
if (type->isEnum()) {
- const auto enumEntry = static_cast<const EnumTypeEntry *>(type);
- if (const auto *nullValue = enumEntry->nullValue())
+ const auto enumEntry = std::static_pointer_cast<const EnumTypeEntry>(type);
+ if (const auto nullValue = enumEntry->nullValue())
return DefaultValue(DefaultValue::Enum, nullValue->name());
return DefaultValue(DefaultValue::Custom,
- u"static_cast< ::"_s + type->qualifiedCppName()
- + u">(0)"_s);
+ "static_cast< "_L1 + getFullTypeName(type) + ">(0)"_L1);
}
if (type->isFlags()) {
@@ -561,7 +447,7 @@ std::optional<DefaultValue>
}
if (type->isPrimitive()) {
- QString ctor = static_cast<const PrimitiveTypeEntry *>(type)->defaultConstructor();
+ QString ctor = std::static_pointer_cast<const PrimitiveTypeEntry>(type)->defaultConstructor();
// If a non-C++ (i.e. defined by the user) primitive type does not have
// a default constructor defined by the user, the empty constructor is
// heuristically returned. If this is wrong the build of the generated
@@ -598,13 +484,13 @@ static QString constructorCall(const QString &qualifiedCppName, const QStringLis
std::optional<DefaultValue>
Generator::minimalConstructor(const ApiExtractorResult &api,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
QString *errorString)
{
if (!metaClass)
return {};
- auto cType = static_cast<const ComplexTypeEntry *>(metaClass->typeEntry());
+ auto cType = std::static_pointer_cast<const ComplexTypeEntry>(metaClass->typeEntry());
if (cType->hasDefaultConstructor())
return DefaultValue(DefaultValue::Custom, cType->defaultConstructor());
@@ -629,12 +515,12 @@ std::optional<DefaultValue>
// Examine arguments, exclude functions taking a self parameter
bool simple = true;
bool suitable = true;
- for (int i = 0, size = arguments.size();
+ for (qsizetype i = 0, size = arguments.size();
suitable && i < size && !arguments.at(i).hasOriginalDefaultValueExpression(); ++i) {
const AbstractMetaArgument &arg = arguments.at(i);
- const TypeEntry *aType = arg.type().typeEntry();
+ TypeEntryCPtr aType = arg.type().typeEntry();
suitable &= aType != cType;
- simple &= aType->isCppPrimitive() || aType->isEnum() || arg.type().isPointer();
+ simple &= isCppPrimitive(aType) || aType->isEnum() || arg.type().isPointer();
}
if (suitable)
candidates.insert(arguments.size() + (simple ? 0 : 100), ctor);
@@ -644,8 +530,7 @@ std::optional<DefaultValue>
for (auto it = candidates.cbegin(), end = candidates.cend(); it != end; ++it) {
const AbstractMetaArgumentList &arguments = it.value()->arguments();
QStringList args;
- for (int i = 0, size = arguments.size(); i < size; ++i) {
- const AbstractMetaArgument &arg = arguments.at(i);
+ for (const auto &arg : arguments) {
if (arg.hasModifiedDefaultValueExpression()) {
args << arg.defaultValueExpression(); // Spell out modified values
break;
@@ -664,7 +549,7 @@ std::optional<DefaultValue>
}
QString Generator::translateType(AbstractMetaType cType,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
Options options) const
{
QString s;
@@ -680,20 +565,20 @@ QString Generator::translateType(AbstractMetaType cType,
} else if (cType.isArray()) {
s = translateType(*cType.arrayElementType(), context, options) + u"[]"_s;
} else {
+ AbstractMetaType copyType = cType;
if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) {
- AbstractMetaType copyType = cType;
-
if (options & Generator::ExcludeConst)
copyType.setConstant(false);
-
if (options & Generator::ExcludeReference)
copyType.setReferenceType(NoReference);
+ }
- s = copyType.cppSignature();
- if (!copyType.typeEntry()->isVoid() && !copyType.typeEntry()->isCppPrimitive())
- s.prepend(u"::"_s);
- } else {
- s = cType.cppSignature();
+ s = copyType.cppSignature();
+ const auto te = copyType.typeEntry();
+ if (!te->isVoid() && !isCppPrimitive(te)) { // Add scope resolution
+ const auto pos = s.indexOf(te->qualifiedCppName()); // Skip const/volatile
+ Q_ASSERT(pos >= 0);
+ s.insert(pos, u"::"_s);
}
}
@@ -717,7 +602,6 @@ static const QHash<QString, QString> &pythonOperators()
{u"operator++"_s, u"__iadd__"_s},
{u"operator--"_s, u"__isub__"_s},
{u"operator*="_s, u"__imul__"_s},
- {u"operator/="_s, u"__idiv__"_s},
{u"operator%="_s, u"__imod__"_s},
// Bitwise operators
{u"operator&"_s, u"__and__"_s},
@@ -738,7 +622,10 @@ static const QHash<QString, QString> &pythonOperators()
{u"operator<"_s, u"__lt__"_s},
{u"operator>"_s, u"__gt__"_s},
{u"operator<="_s, u"__le__"_s},
- {u"operator>="_s, u"__ge__"_s}
+ {u"operator>="_s, u"__ge__"_s},
+ // Conversion (note bool has special handling with heuristics)
+ {u"operator int"_s, u"__int__"_s},
+ {u"operator double"_s, u"__float__"_s}
};
return result;
}
@@ -748,6 +635,11 @@ QString Generator::pythonOperatorFunctionName(const QString &cppOpFuncName)
return pythonOperators().value(cppOpFuncName);
}
+bool Generator::isPythonOperatorFunctionName(const QString &cppOpFuncName)
+{
+ return pythonOperators().contains(cppOpFuncName);
+}
+
QString Generator::subDirectoryForPackage(QString packageNameIn) const
{
if (packageNameIn.isEmpty())
@@ -756,11 +648,21 @@ QString Generator::subDirectoryForPackage(QString packageNameIn) const
return packageNameIn;
}
+QString Generator::addGlobalScopePrefix(const QString &t)
+{
+ return t.startsWith("std::"_L1) ? t : m_gsp + t;
+}
+
+QString Generator::globalScopePrefix(const GeneratorContext &classContext)
+{
+ return classContext.useWrapper() ? QString{} : m_gsp;
+}
+
template<typename T>
-static QString getClassTargetFullName_(const T *t, bool includePackageName)
+static QString getClassTargetFullName_(T t, bool includePackageName)
{
QString name = t->name();
- const AbstractMetaClass *context = t->enclosingClass();
+ AbstractMetaClassCPtr context = t->enclosingClass();
while (context) {
// If the type was marked as 'visible=false' we should not use it in
// the type name
@@ -777,12 +679,14 @@ static QString getClassTargetFullName_(const T *t, bool includePackageName)
return name;
}
-QString getClassTargetFullName(const AbstractMetaClass *metaClass, bool includePackageName)
+QString getClassTargetFullName(const AbstractMetaClassCPtr &metaClass,
+ bool includePackageName)
{
return getClassTargetFullName_(metaClass, includePackageName);
}
-QString getClassTargetFullName(const AbstractMetaEnum &metaEnum, bool includePackageName)
+QString getClassTargetFullName(const AbstractMetaEnum &metaEnum,
+ bool includePackageName)
{
return getClassTargetFullName_(&metaEnum, includePackageName);
}
diff --git a/sources/shiboken6/generator/generator.h b/sources/shiboken6/generator/generator.h
index 1d1a0caeb..5b051b599 100644
--- a/sources/shiboken6/generator/generator.h
+++ b/sources/shiboken6/generator/generator.h
@@ -4,163 +4,37 @@
#ifndef GENERATOR_H
#define GENERATOR_H
-#include <abstractmetatype.h>
+#include <abstractmetalang_typedefs.h>
#include <typedatabase_typedefs.h>
-#include <QtCore/QObject>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QTextStream>
#include <QtCore/QList>
+#include <memory>
#include <optional>
+
class ApiExtractorResult;
-class AbstractMetaFunction;
-class AbstractMetaClass;
-class AbstractMetaEnum;
-class TypeEntry;
-class ComplexTypeEntry;
-class AbstractMetaType;
-class EnumTypeEntry;
-class FlagsTypeEntry;
+class GeneratorContext;
+class DefaultValue;
+struct OptionDescription;
+class OptionsParser;
class TextStream;
-QT_BEGIN_NAMESPACE
-class QFile;
-class QDebug;
-QT_END_NAMESPACE
-
-class PrimitiveTypeEntry;
-class ContainerTypeEntry;
-
-QString getClassTargetFullName(const AbstractMetaClass *metaClass, bool includePackageName = true);
-QString getClassTargetFullName(const AbstractMetaEnum &metaEnum, bool includePackageName = true);
+QString getClassTargetFullName(const AbstractMetaClassCPtr &metaClass,
+ bool includePackageName = true);
+QString getClassTargetFullName(const AbstractMetaEnum &metaEnum,
+ bool includePackageName = true);
QString getFilteredCppSignatureString(QString signature);
/**
- * PYSIDE-504: Handling the "protected hack"
- *
- * The problem: Creating wrappers when the class has private destructors.
- * You can see an example on Windows in qclipboard_wrapper.h and others.
- * Simply search for the text "// C++11: need to declare (unimplemented) destructor".
- *
- * The protected hack is the definition "#define protected public".
- * For most compilers, this "hack" is enabled, because the problem of private
- * destructors simply vanishes.
- *
- * If one does not want to use this hack, then a new problem arises:
- * C++11 requires that a destructor is declared in a wrapper class when it is
- * private in the base class. There is no implementation allowed!
- *
- * Unfortunately, MSVC in recent versions supports C++11, and due to restrictive
- * rules, it is impossible to use the hack with this compiler.
- * More unfortunate: Clang, when C++11 is enabled, also enforces a declaration
- * of a private destructor, but it falsely then creates a linker error!
- *
- * Originally, we wanted to remove the protected hack. But due to the Clang
- * problem, we gave up on removal of the protected hack and use it always
- * when we can. This might change again when the Clang problem is solved.
- */
-
-#ifdef Q_CC_MSVC
-const int alwaysGenerateDestructor = 1;
-#else
-const int alwaysGenerateDestructor = 0;
-#endif
-
-class DefaultValue
-{
-public:
- enum Type
- {
- Boolean,
- CppScalar, // A C++ scalar type (int,..) specified by value()
- Custom, // A custom constructor/expression, uses value() as is
- DefaultConstructor, // For classes named value()
- DefaultConstructorWithDefaultValues, // as DefaultConstructor, but can't return {} though.
- Enum, // Enum value as specified by value()
- Pointer, // Pointer of type value()
- Void // "", for return values only
- };
-
- explicit DefaultValue(Type t, QString value = QString());
- explicit DefaultValue(QString customValue);
-
- QString returnValue() const;
- QString initialization() const;
- QString constructorParameter() const;
-
- QString value() const { return m_value; }
- void setValue(const QString &value) { m_value = value; }
-
- Type type() const { return m_type; }
- void setType(Type type) { m_type = type; }
-
-private:
- Type m_type;
- QString m_value;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const DefaultValue &v);
-#endif
-
-/**
- * A GeneratorContext object contains a pointer to an AbstractMetaClass and/or a specialized
- * AbstractMetaType, for which code is currently being generated.
- *
- * The main case is when the context contains only an AbstractMetaClass pointer, which is used
- * by different methods to generate appropriate expressions, functions, type names, etc.
- *
- * The second case is for generation of code for smart pointers. In this case the m_metaClass member
- * contains the generic template class of the smart pointer, and the m_preciseClassType member
- * contains the instantiated template type, e.g. a concrete shared_ptr<int>. To
- * distinguish this case, the member m_forSmartPointer is set to true.
- *
- * In the future the second case might be generalized for all template type instantiations.
- */
-class GeneratorContext {
- friend class ShibokenGenerator;
- friend class Generator;
-public:
- enum Type { Class, WrappedClass, SmartPointer };
-
- GeneratorContext() = default;
-
- const AbstractMetaClass *metaClass() const { return m_metaClass; }
- const AbstractMetaType &preciseType() const { return m_preciseClassType; }
- const AbstractMetaClass *pointeeClass() const { return m_pointeeClass; }
-
- bool forSmartPointer() const { return m_type == SmartPointer; }
- bool useWrapper() const { return m_type == WrappedClass; }
-
- QString wrapperName() const;
- /// Returns the wrapper name in case of useWrapper(), the qualified class
- /// name or the smart pointer specialization.
- QString effectiveClassName() const;
-
-private:
- const AbstractMetaClass *m_metaClass = nullptr;
- const AbstractMetaClass *m_pointeeClass = nullptr;
- AbstractMetaType m_preciseClassType;
- QString m_wrappername;
- Type m_type = Class;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const GeneratorContext &c);
-#endif
-
-/**
* Base class for all generators. The default implementations does nothing,
* you must subclass this to create your own generators.
*/
class Generator
-{
+{;
public:
- using OptionDescription = QPair<QString, QString>;
- using OptionDescriptions = QList<OptionDescription>;
+ Q_DISABLE_COPY_MOVE(Generator)
- /// Optiosn used around the generator code
+ /// Options used around the generator code
enum Option {
NoOption = 0x00000000,
ExcludeConst = 0x00000001,
@@ -186,8 +60,8 @@ public:
bool setup(const ApiExtractorResult &api);
- virtual OptionDescriptions options() const;
- virtual bool handleOption(const QString &key, const QString &value);
+ static QList<OptionDescription> options();
+ static std::shared_ptr<OptionsParser> createOptionsParser();
/// Returns the top namespace made invisible
const AbstractMetaClassCList &invisibleTopNamespaces() const;
@@ -221,10 +95,10 @@ public:
bool hasPrivateClasses() const;
/// Returns true if the user enabled PySide extensions (command line option)
- bool usePySideExtensions() const;
+ static bool usePySideExtensions();
/// Returns true if the generated code should not use the
/// "#define protected public" hack.
- bool avoidProtectedHack() const;
+ static bool avoidProtectedHack();
/**
* Retrieves the name of the currently processed module.
@@ -236,6 +110,9 @@ public:
*/
static QString moduleName();
+ static QString pythonOperatorFunctionName(const QString &cppOpFuncName);
+ static bool isPythonOperatorFunctionName(const QString &cppOpFuncName);
+
protected:
/// Helper for determining the file name
static QString fileNameForContextHelper(const GeneratorContext &context,
@@ -243,15 +120,15 @@ protected:
FileNameFlags flags = {});
/// Returns all primitive types found by APIExtractor
- static PrimitiveTypeEntryList primitiveTypes();
+ static PrimitiveTypeEntryCList primitiveTypes();
/// Returns all container types found by APIExtractor
- static ContainerTypeEntryList containerTypes();
+ static ContainerTypeEntryCList containerTypes();
- virtual GeneratorContext contextForClass(const AbstractMetaClass *c) const;
- static GeneratorContext contextForSmartPointer(const AbstractMetaClass *c,
- const AbstractMetaType &t,
- const AbstractMetaClass *pointeeClass = nullptr);
+ virtual GeneratorContext contextForClass(const AbstractMetaClassCPtr &c) const;
+ static GeneratorContext
+ contextForSmartPointer(const AbstractMetaClassCPtr &c, const AbstractMetaType &t,
+ const AbstractMetaClassCPtr &pointeeClass = {});
/// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case).
bool generateFileForContext(const GeneratorContext &context);
@@ -260,7 +137,7 @@ protected:
static QString getFileNameBaseForSmartPointer(const AbstractMetaType &smartPointerType);
/// Returns true if the generator should generate any code for the AbstractMetaClass.
- virtual bool shouldGenerate(const TypeEntry *t) const;
+ virtual bool shouldGenerate(const TypeEntryCPtr &t) const;
/**
* Translate metatypes to binding source format.
@@ -270,20 +147,18 @@ protected:
* \return the metatype translated to binding source format
*/
QString translateType(AbstractMetaType metatype,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
Options options = NoOption) const;
- static QString pythonOperatorFunctionName(const QString &cppOpFuncName);
-
/**
* Returns the package name.
*/
static QString packageName();
// Returns the full name of the type.
- static QString getFullTypeName(const TypeEntry *type);
+ static QString getFullTypeName(TypeEntryCPtr type);
static QString getFullTypeName(const AbstractMetaType &type);
- static QString getFullTypeName(const AbstractMetaClass *metaClass);
+ static QString getFullTypeName(const AbstractMetaClassCPtr &metaClass);
/**
* Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers
@@ -298,14 +173,14 @@ protected:
* Returns a null string if it fails.
*/
static std::optional<DefaultValue>
- minimalConstructor(const ApiExtractorResult &api, const TypeEntry *type,
+ minimalConstructor(const ApiExtractorResult &api, const TypeEntryCPtr &type,
QString *errorString = nullptr);
static std::optional<DefaultValue>
minimalConstructor(const ApiExtractorResult &api, const AbstractMetaType &type,
QString *errorString = nullptr);
static std::optional<DefaultValue>
minimalConstructor(const ApiExtractorResult &api,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
QString *errorString = nullptr);
/**
@@ -339,6 +214,11 @@ protected:
*/
virtual QString subDirectoryForPackage(QString packageName = QString()) const;
+ static QString addGlobalScopePrefix(const QString &t);
+ static QString globalScopePrefix(const GeneratorContext &classContext);
+
+ static QString m_gsp;
+
private:
struct GeneratorPrivate;
GeneratorPrivate *m_d;
@@ -347,8 +227,7 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options)
Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::FileNameFlags)
-using GeneratorPtr = QSharedPointer<Generator>;
+using GeneratorPtr = std::shared_ptr<Generator>;
using Generators = QList<GeneratorPtr>;
#endif // GENERATOR_H
-
diff --git a/sources/shiboken6/generator/generatorcontext.cpp b/sources/shiboken6/generator/generatorcontext.cpp
new file mode 100644
index 000000000..b50c2effb
--- /dev/null
+++ b/sources/shiboken6/generator/generatorcontext.cpp
@@ -0,0 +1,38 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "generatorcontext.h"
+#include <abstractmetalang.h>
+
+#include <QtCore/QDebug>
+
+using namespace Qt::StringLiterals;
+
+QString GeneratorContext::wrapperName() const
+{
+ Q_ASSERT(m_type == WrappedClass);
+ return m_wrappername;
+}
+
+QString GeneratorContext::effectiveClassName() const
+{
+ if (m_type == SmartPointer)
+ return m_preciseClassType.cppSignature();
+ return m_type == WrappedClass ? m_wrappername : m_metaClass->qualifiedCppName();
+}
+
+QDebug operator<<(QDebug debug, const GeneratorContext &c)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "GeneratorContext(\"" << c.metaClass()->name() << "\" ";
+ if (c.useWrapper())
+ debug << "[wrapper]";
+ else if (c.forSmartPointer())
+ debug << "[smart pointer] \"" << c.preciseType().cppSignature() << '"';
+ else
+ debug << "[class]";
+ debug << ')';
+ return debug;
+}
diff --git a/sources/shiboken6/generator/generatorcontext.h b/sources/shiboken6/generator/generatorcontext.h
new file mode 100644
index 000000000..2e58d4346
--- /dev/null
+++ b/sources/shiboken6/generator/generatorcontext.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef GENERATORCONTEXT_H
+#define GENERATORCONTEXT_H
+
+#include <abstractmetalang_typedefs.h>
+#include <abstractmetatype.h>
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QDebug);
+
+// A GeneratorContext object contains a pointer to an AbstractMetaClass and/or a specialized
+// AbstractMetaType, for which code is currently being generated.
+//
+// The main case is when the context contains only an AbstractMetaClass pointer, which is used
+// by different methods to generate appropriate expressions, functions, type names, etc.
+//
+// The second case is for generation of code for smart pointers. In this case the m_metaClass
+// member contains the generic template class of the smart pointer, and the m_preciseClassType
+// member contains the instantiated template type, e.g. a concrete shared_ptr<int>. To
+// distinguish this case, the member m_forSmartPointer is set to true.
+//
+// In the future the second case might be generalized for all template type instantiations.
+
+class GeneratorContext {
+ friend class ShibokenGenerator;
+ friend class Generator;
+public:
+ enum Type { Class, WrappedClass, SmartPointer };
+
+ GeneratorContext() = default;
+
+ AbstractMetaClassCPtr metaClass() const { return m_metaClass; }
+ const AbstractMetaType &preciseType() const { return m_preciseClassType; }
+ AbstractMetaClassCPtr pointeeClass() const { return m_pointeeClass; }
+
+ bool forSmartPointer() const { return m_type == SmartPointer; }
+ bool useWrapper() const { return m_type == WrappedClass; }
+
+ QString wrapperName() const;
+ /// Returns the wrapper name in case of useWrapper(), the qualified class
+ /// name or the smart pointer specialization.
+ QString effectiveClassName() const;
+
+private:
+ AbstractMetaClassCPtr m_metaClass;
+ AbstractMetaClassCPtr m_pointeeClass;
+ AbstractMetaType m_preciseClassType;
+ QString m_wrappername;
+ Type m_type = Class;
+};
+
+QDebug operator<<(QDebug debug, const GeneratorContext &c);
+
+#endif // GENERATORCONTEXT_H
diff --git a/sources/shiboken6/generator/main.cpp b/sources/shiboken6/generator/main.cpp
index d891d499c..9871df206 100644
--- a/sources/shiboken6/generator/main.cpp
+++ b/sources/shiboken6/generator/main.cpp
@@ -9,12 +9,13 @@
#include <apiextractor.h>
#include <apiextractorresult.h>
+#include <exception.h>
#include <fileout.h>
#include <messages.h>
+#include <optionsparser.h>
#include <reporthandler.h>
#include <typedatabase.h>
-#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QLibrary>
@@ -27,267 +28,8 @@
using namespace Qt::StringLiterals;
-static const QChar clangOptionsSplitter = u',';
-static const QChar keywordsSplitter = u',';
-static const QChar dropTypeEntriesSplitter = u';';
-static const QChar apiVersionSplitter = u'|';
-
-static inline QString keywordsOption() { return QStringLiteral("keywords"); }
-static inline QString clangOptionOption() { return QStringLiteral("clang-option"); }
-static inline QString clangOptionsOption() { return QStringLiteral("clang-options"); }
-static inline QString apiVersionOption() { return QStringLiteral("api-version"); }
-static inline QString dropTypeEntriesOption() { return QStringLiteral("drop-type-entries"); }
-static inline QString languageLevelOption() { return QStringLiteral("language-level"); }
-static inline QString includePathOption() { return QStringLiteral("include-paths"); }
-static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); }
-static inline QString systemIncludePathOption() { return QStringLiteral("system-include-paths"); }
-static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); }
-static inline QString helpOption() { return QStringLiteral("help"); }
-static inline QString diffOption() { return QStringLiteral("diff"); }
-static inline QString useGlobalHeaderOption() { return QStringLiteral("use-global-header"); }
-static inline QString dryrunOption() { return QStringLiteral("dry-run"); }
-static inline QString skipDeprecatedOption() { return QStringLiteral("skip-deprecated"); }
-
static const char helpHint[] = "Note: use --help or -h for more information.\n";
-
-using OptionDescriptions = Generator::OptionDescriptions;
-
-struct CommandLineArguments
-{
- void addToOptionsList(const QString &option,
- const QString &value);
- void addToOptionsList(const QString &option,
- const QStringList &value);
- void addToOptionsList(const QString &option,
- const QString &listValue,
- QChar separator);
- void addToOptionsPathList(const QString &option,
- const QString &pathListValue)
- {
- addToOptionsList(option, pathListValue, QDir::listSeparator());
- }
-
- QVariantMap options; // string,stringlist for path lists, etc.
- QStringList positionalArguments;
-};
-
-void CommandLineArguments::addToOptionsList(const QString &option,
- const QString &value)
-{
- auto it = options.find(option);
- if (it == options.end()) {
- options.insert(option, QVariant(QStringList(value)));
- } else {
- auto list = it.value().toStringList();
- list += value;
- options[option] = QVariant(list);
- }
-}
-
-void CommandLineArguments::addToOptionsList(const QString &option,
- const QStringList &value)
-{
- auto it = options.find(option);
- if (it == options.end()) {
- options.insert(option, QVariant(value));
- } else {
- auto list = it.value().toStringList();
- list += value;
- options[option] = QVariant(list);
- }
-}
-
-void CommandLineArguments::addToOptionsList(const QString &option,
- const QString &listValue,
- QChar separator)
-{
- const auto newValues = listValue.split(separator, Qt::SkipEmptyParts);
- addToOptionsList(option, newValues);
-}
-
-static void printOptions(QTextStream &s, const OptionDescriptions &options)
-{
- s.setFieldAlignment(QTextStream::AlignLeft);
- for (const auto &od : options) {
- if (!od.first.startsWith(u'-'))
- s << "--";
- s << od.first;
- if (od.second.isEmpty()) {
- s << ", ";
- } else {
- s << Qt::endl;
- const auto lines = QStringView{od.second}.split(u'\n');
- for (const auto &line : lines)
- s << " " << line << Qt::endl;
- s << Qt::endl;
- }
- }
-}
-
-static std::optional<CommandLineArguments>
- processProjectFile(const QString &appName, QFile &projectFile)
-{
- QByteArray line = projectFile.readLine().trimmed();
- if (line.isEmpty() || line != "[generator-project]") {
- std::cerr << qPrintable(appName) << ": first line of project file \""
- << qPrintable(projectFile.fileName())
- << "\" must be the string \"[generator-project]\"\n";
- return {};
- }
-
- CommandLineArguments args;
-
- while (!projectFile.atEnd()) {
- line = projectFile.readLine().trimmed();
- if (line.isEmpty())
- continue;
-
- int split = line.indexOf('=');
- QByteArray key;
- QString value;
- if (split > 0) {
- key = line.left(split).trimmed();
- value = QString::fromUtf8(line.mid(split + 1).trimmed());
- } else {
- key = line;
- }
-
- if (key == "include-path") {
- args.addToOptionsList(includePathOption(),
- QDir::toNativeSeparators(value));
- } else if (key == "framework-include-path") {
- args.addToOptionsList(frameworkIncludePathOption(),
- QDir::toNativeSeparators(value));
- } else if (key == "system-include-paths") {
- args.addToOptionsList(systemIncludePathOption(),
- QDir::toNativeSeparators(value));
- } else if (key == "typesystem-path") {
- args.addToOptionsList(typesystemPathOption(),
- QDir::toNativeSeparators(value));
- } else if (key == "language-level") {
- args.options.insert(languageLevelOption(), value);
- } else if (key == "clang-option") {
- args.addToOptionsList(clangOptionsOption(), value);
- } else if (key == "clang-options") {
- args.addToOptionsList(clangOptionsOption(),
- value, clangOptionsSplitter);
- } else if (key == "api-version") {
- args.addToOptionsList(apiVersionOption(),
- value, apiVersionSplitter);
- } else if (key == "keywords") {
- args.addToOptionsList(keywordsOption(),
- value, keywordsSplitter);
- } else if (key == "drop-type-entries") {
- args.addToOptionsList(dropTypeEntriesOption(),
- value, dropTypeEntriesSplitter);
- } else if (key == "header-file") {
- args.positionalArguments.prepend(value);
- } else if (key == "typesystem-file") {
- args.positionalArguments.append(value);
- } else {
- args.options.insert(QString::fromUtf8(key), value);
- }
- }
-
- return args;
-}
-
-static std::optional<CommandLineArguments> getProjectFileArguments()
-{
- QStringList arguments = QCoreApplication::arguments();
- QString appName = arguments.constFirst();
- arguments.removeFirst();
-
- QString projectFileName;
- for (const QString &arg : qAsConst(arguments)) {
- if (arg.startsWith(u"--project-file")) {
- int split = arg.indexOf(u'=');
- if (split > 0)
- projectFileName = arg.mid(split + 1).trimmed();
- break;
- }
- }
-
- if (projectFileName.isEmpty())
- return CommandLineArguments{};
-
- if (!QFile::exists(projectFileName)) {
- std::cerr << qPrintable(appName) << ": Project file \""
- << qPrintable(projectFileName) << "\" not found.\n";
- return {};
- }
-
- QFile projectFile(projectFileName);
- if (!projectFile.open(QIODevice::ReadOnly)) {
- std::cerr << qPrintable(appName) << ": Cannot open project file \""
- << qPrintable(projectFileName) << "\" : " << qPrintable(projectFile.errorString())
- << '\n';
- return {};
- }
- return processProjectFile(appName, projectFile);
-}
-
-static void getCommandLineArg(QString arg, int &argNum, CommandLineArguments &args)
-{
- if (arg.startsWith(u"--")) {
- arg.remove(0, 2);
- const int split = arg.indexOf(u'=');
- if (split < 0) {
- args.options.insert(arg, QString());
- return;
- }
- const QString option = arg.left(split);
- const QString value = arg.mid(split + 1).trimmed();
- if (option == includePathOption() || option == frameworkIncludePathOption()
- || option == systemIncludePathOption() || option == typesystemPathOption()) {
- args.addToOptionsPathList(option, value);
- } else if (option == apiVersionOption()) {
- args.addToOptionsList(apiVersionOption(), value, apiVersionSplitter);
- } else if (option == dropTypeEntriesOption()) {
- args.addToOptionsList(dropTypeEntriesOption(), value, dropTypeEntriesSplitter);
- } else if (option == clangOptionOption()) {
- args.addToOptionsList(clangOptionsOption(), value);
- } else if (option == clangOptionsOption()) {
- args.addToOptionsList(clangOptionsOption(), value, clangOptionsSplitter);
- } else if (option == keywordsOption()) {
- args.addToOptionsList(keywordsOption(), value, keywordsSplitter);
- } else {
- args.options.insert(option, value);
- }
- return;
- }
- if (arg.startsWith(u'-')) {
- arg.remove(0, 1);
- if (arg.startsWith(u'I')) // Shorthand path arguments -I/usr/include...
- args.addToOptionsPathList(includePathOption(), arg.mid(1));
- else if (arg.startsWith(u'F'))
- args.addToOptionsPathList(frameworkIncludePathOption(), arg.mid(1));
- else if (arg.startsWith(u"isystem"))
- args.addToOptionsPathList(systemIncludePathOption(), arg.mid(7));
- else if (arg.startsWith(u'T'))
- args.addToOptionsPathList(typesystemPathOption(), arg.mid(1));
- else if (arg == u"h")
- args.options.insert(helpOption(), QString());
- else if (arg.startsWith(u"std="))
- args.options.insert(languageLevelOption(), arg.mid(4));
- else
- args.options.insert(arg, QString());
- return;
- }
- if (argNum < args.positionalArguments.size())
- args.positionalArguments[argNum] = arg;
- else
- args.positionalArguments.append(arg);
- ++argNum;
-}
-
-static void getCommandLineArgs(CommandLineArguments &args)
-{
- const QStringList arguments = QCoreApplication::arguments();
- int argNum = 0;
- for (int i = 1, size = arguments.size(); i < size; ++i)
- getCommandLineArg(arguments.at(i).trimmed(), argNum, args);
-}
+static const char appName[] = "shiboken";
static inline Generators docGenerators()
{
@@ -305,60 +47,57 @@ static inline Generators shibokenGenerators()
return result;
}
-static inline QString languageLevelDescription()
+struct CommonOptions
{
- return u"C++ Language level (c++11..c++17, default="_s
- + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
- + u')';
-}
+ QString generatorSet;
+ QString licenseComment;
+ QString outputDirectory = u"out"_s;
+ QStringList headers;
+ QString typeSystemFileName;
+ bool help = false;
+ bool version = false;
+ bool diff = false;
+ bool dryRun = false;
+ bool logUnmatched = false;
+ bool printBuiltinTypes = false;
+};
-void printUsage()
+class CommonOptionsParser : public OptionsParser
{
- const QChar pathSplitter = QDir::listSeparator();
- QTextStream s(stdout);
- s << "Usage:\n "
- << "shiboken [options] header-file(s) typesystem-file\n\n"
- << "General options:\n";
- QString pathSyntax;
- QTextStream(&pathSyntax) << "<path>[" << pathSplitter << "<path>"
- << pathSplitter << "...]";
- OptionDescriptions generalOptions = {
- {u"api-version=<\"package mask\">,<\"version\">"_s,
- u"Specify the supported api version used to generate the bindings"_s},
+public:
+ explicit CommonOptionsParser(CommonOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value, OptionSource source) override;
+
+ static OptionDescriptions optionDescriptions();
+
+private:
+ CommonOptions *m_options;
+};
+
+OptionDescriptions CommonOptionsParser::optionDescriptions()
+{
+ return {
{u"debug-level=[sparse|medium|full]"_s,
u"Set the debug level"_s},
{u"documentation-only"_s,
u"Do not generates any code, just the documentation"_s},
- {u"drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""_s,
- u"Semicolon separated list of type system entries (classes, namespaces,\n"
- "global functions and enums) to be dropped from generation."_s},
- {keywordsOption() + QStringLiteral("=keyword1[,keyword2,...]"),
- u"A comma-separated list of keywords for conditional typesystem parsing"_s},
- {clangOptionOption(),
- u"Option to be passed to clang"_s},
- {clangOptionsOption(),
- u"A comma-separated list of options to be passed to clang"_s},
- {u"-F<path>"_s, {} },
- {u"framework-include-paths="_s + pathSyntax,
- u"Framework include paths used by the C++ parser"_s},
- {u"-isystem<path>"_s, {} },
- {u"system-include-paths="_s + pathSyntax,
- u"System include paths used by the C++ parser"_s},
- {useGlobalHeaderOption(),
- u"Use the global headers in generated code."_s},
+ {u"compiler=<type>"_s,
+ u"Emulated compiler type (g++, msvc, clang)"_s},
+ {u"platform=<name>"_s,
+ u"Emulated platform (windows, darwin, unix)"_s},
+ {u"compiler-path=<file>"_s,
+ u"Path to the compiler for determining builtin include paths"_s},
{u"generator-set=<\"generator module\">"_s,
u"generator-set to be used. e.g. qtdoc"_s},
- {skipDeprecatedOption(),
- u"Skip deprecated functions"_s},
- {diffOption(), u"Print a diff of wrapper files"_s},
- {dryrunOption(), u"Dry run, do not generate wrapper files"_s},
+ {u"diff"_s, u"Print a diff of wrapper files"_s},
+ {u"dry-run"_s, u"Dry run, do not generate wrapper files"_s},
{u"-h"_s, {} },
- {helpOption(), u"Display this help and exit"_s},
+ {u"help"_s, u"Display this help and exit"_s},
{u"-I<path>"_s, {} },
- {u"include-paths="_s + pathSyntax,
+ {u"include-paths="_s + OptionsParser::pathSyntax(),
u"Include paths used by the C++ parser"_s},
- {languageLevelOption() + u"=, -std=<level>"_s,
- languageLevelDescription()},
{u"license-file=<license-file>"_s,
u"File used for copyright headers of generated files"_s},
{u"no-suppress-warnings"_s,
@@ -369,306 +108,252 @@ void printUsage()
u"text file containing a description of the binding project.\n"
"Replaces and overrides command line arguments"_s},
{u"silent"_s, u"Avoid printing any message"_s},
- {u"-T<path>"_s, {} },
- {u"typesystem-paths="_s + pathSyntax,
- u"Paths used when searching for typesystems"_s},
+ {u"print-builtin-types"_s,
+ u"Print information about builtin types"_s},
{u"version"_s,
u"Output version information and exit"_s}
};
- printOptions(s, generalOptions);
-
- const Generators generators = shibokenGenerators() + docGenerators();
- for (const GeneratorPtr &generator : generators) {
- const OptionDescriptions options = generator->options();
- if (!options.isEmpty()) {
- s << Qt::endl << generator->name() << " options:\n\n";
- printOptions(s, generator->options());
+}
+
+bool CommonOptionsParser::handleBoolOption(const QString &key, OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash) {
+ if (key == u"h") {
+ m_options->help = true;
+ return true;
+ }
+ return false;
+ }
+
+ if (key == u"version") {
+ m_options->version = true;
+ return true;
+ }
+ if (key == u"help") {
+ m_options->help = true;
+ return true;
+ }
+ if (key == u"diff") {
+ FileOut::setDiff(true);
+ return true;
+ }
+ if (key == u"dry-run") {
+ FileOut::setDryRun(true);
+ return true;
+ }
+ if (key == u"silent") {
+ ReportHandler::setSilent(true);
+ return true;
+ }
+ if (key == u"log-unmatched") {
+ m_options->logUnmatched = true;
+ return true;
+ }
+ if (key == u"print-builtin-types") {
+ m_options->printBuiltinTypes = true;
+ return true;
+ }
+
+ return false;
+}
+
+bool CommonOptionsParser::handleOption(const QString &key, const QString &value,
+ OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
+
+ if (key == u"generator-set" || key == u"generatorSet" /* legacy */) {
+ m_options->generatorSet = value;
+ return true;
+ }
+ if (key == u"license-file") {
+ QFile licenseFile(value);
+ if (!licenseFile.open(QIODevice::ReadOnly))
+ throw Exception(msgCannotOpenForReading(licenseFile));
+ m_options->licenseComment = QString::fromUtf8(licenseFile.readAll());
+ return true;
+ }
+ if (key == u"debug-level") {
+ if (!ReportHandler::setDebugLevelFromArg(value))
+ throw Exception(u"Invalid debug level: "_s + value);
+ return true;
+ }
+ if (key == u"output-directory") {
+ m_options->outputDirectory = value;
+ return true;
+ }
+ if (key == u"compiler") {
+ if (!clang::setCompiler(value))
+ throw Exception(u"Invalid value \""_s + value + u"\" passed to --compiler"_s);
+ return true;
+ }
+ if (key == u"compiler-path") {
+ clang::setCompilerPath(value);
+ return true;
+ }
+ if (key == u"platform") {
+ if (!clang::setPlatform(value))
+ throw Exception(u"Invalid value \""_s + value + u"\" passed to --platform"_s);
+ return true;
+ }
+
+ if (source == OptionSource::ProjectFile) {
+ if (key == u"header-file") {
+ m_options->headers.append(value);
+ return true;
+ }
+ if (key == u"typesystem-file") {
+ m_options->typeSystemFileName = value;
+ return true;
}
}
+
+ return false;
+}
+
+void printUsage()
+{
+ const auto generatorOptions = Generator::options();
+
+ QTextStream s(stdout);
+ s << "Usage:\n "
+ << "shiboken [options] header-file(s) typesystem-file\n\n"
+ << "General options:\n"
+ << CommonOptionsParser::optionDescriptions()
+ << ApiExtractor::options()
+ << TypeDatabase::options()
+ << "\nSource generator options:\n\n" << generatorOptions
+ << ShibokenGenerator::options();
+
+#ifdef DOCSTRINGS_ENABLED
+ s << "\nDocumentation Generator options:\n\n"
+ << generatorOptions << QtDocGenerator::options();
+#endif
}
static inline void printVerAndBanner()
{
- std::cout << "shiboken v" SHIBOKEN_VERSION << std::endl;
+ std::cout << appName << " v" << SHIBOKEN_VERSION << std::endl;
std::cout << "Copyright (C) 2016 The Qt Company Ltd." << std::endl;
}
-static inline void errorPrint(const QString &s)
+static inline void errorPrint(const QString &s, const QStringList &arguments)
{
- QStringList arguments = QCoreApplication::arguments();
- arguments.pop_front();
- std::cerr << "shiboken: " << qPrintable(s) << "\nCommand line:\n";
+ std::cerr << appName << ": " << qPrintable(s) << "\nCommand line:\n";
for (const auto &argument : arguments)
std::cerr << " \"" << qPrintable(argument) << "\"\n";
}
-static void parseIncludePathOption(const QString &option, HeaderType headerType,
- CommandLineArguments &args,
- ApiExtractor &extractor)
-{
- const auto it = args.options.find(option);
- if (it != args.options.end()) {
- const auto includePathListList = it.value().toStringList();
- args.options.erase(it);
- for (const QString &s : includePathListList) {
- auto path = QFile::encodeName(QDir::cleanPath(s));
- extractor.addIncludePath(HeaderPath{path, headerType});
- }
- }
-}
-
-int shibokenMain(int argc, char *argv[])
+int shibokenMain(const QStringList &argV)
{
// PYSIDE-757: Request a deterministic ordering of QHash in the code model
// and type system.
- qSetGlobalQHashSeed(0);
- // needed by qxmlpatterns
- QCoreApplication app(argc, argv);
+ QHashSeed::setDeterministicGlobalSeed();
+
ReportHandler::install();
if (ReportHandler::isDebug(ReportHandler::SparseDebug))
- qCInfo(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(u' ');
+ qCInfo(lcShiboken()).noquote().nospace() << appName << ' ' << argV.join(u' ');
- // Store command arguments in a map
- const auto projectFileArgumentsOptional = getProjectFileArguments();
- if (!projectFileArgumentsOptional.has_value())
- return EXIT_FAILURE;
+ Options options;
+ options.setOptions(argV);
- const CommandLineArguments projectFileArguments = projectFileArgumentsOptional.value();
- CommandLineArguments args = projectFileArguments;
- getCommandLineArgs(args);
- Generators generators;
-
- auto ait = args.options.find(u"version"_s);
- if (ait != args.options.end()) {
- args.options.erase(ait);
+ CommonOptions commonOptions;
+ {
+ CommonOptionsParser parser(&commonOptions);
+ parser.process(&options);
+ }
+ if (commonOptions.version) {
printVerAndBanner();
return EXIT_SUCCESS;
}
-
- QString generatorSet;
- ait = args.options.find(u"generator-set"_s);
- if (ait == args.options.end()) // Also check "generatorSet" command line argument for backward compatibility.
- ait = args.options.find(u"generatorSet"_s);
- if (ait != args.options.end()) {
- generatorSet = ait.value().toString();
- args.options.erase(ait);
+ if (commonOptions.help) {
+ printUsage();
+ return EXIT_SUCCESS;
}
+ Generators generators;
+
+ OptionsParserList optionParser;
+ optionParser.append(Generator::createOptionsParser());
+ optionParser.append(TypeDatabase::instance()->createOptionsParser());
+ ApiExtractor extractor;
+ optionParser.append(extractor.createOptionsParser());
+
// Pre-defined generator sets.
- if (generatorSet == u"qtdoc") {
+ if (commonOptions.generatorSet == u"qtdoc") {
generators = docGenerators();
if (generators.isEmpty()) {
- errorPrint(u"Doc strings extractions was not enabled in this shiboken build."_s);
+ errorPrint(u"Doc strings extractions was not enabled in this shiboken build."_s, argV);
return EXIT_FAILURE;
}
- } else if (generatorSet.isEmpty() || generatorSet == u"shiboken") {
+#ifdef DOCSTRINGS_ENABLED
+ optionParser.append(QtDocGenerator::createOptionsParser());
+#endif
+ } else if (commonOptions.generatorSet.isEmpty() || commonOptions.generatorSet == u"shiboken") {
generators = shibokenGenerators();
+ optionParser.append(ShibokenGenerator::createOptionsParser());
} else {
- errorPrint(u"Unknown generator set, try \"shiboken\" or \"qtdoc\"."_s);
+ errorPrint(u"Unknown generator set, try \"shiboken\" or \"qtdoc\"."_s, argV);
return EXIT_FAILURE;
}
- ait = args.options.find(u"help"_s);
- if (ait != args.options.end()) {
- args.options.erase(ait);
- printUsage();
- return EXIT_SUCCESS;
- }
-
- ait = args.options.find(diffOption());
- if (ait != args.options.end()) {
- args.options.erase(ait);
- FileOut::setDiff(true);
- }
-
- ait = args.options.find(useGlobalHeaderOption());
- if (ait != args.options.end()) {
- args.options.erase(ait);
- ApiExtractor::setUseGlobalHeader(true);
- }
-
- ait = args.options.find(dryrunOption());
- if (ait != args.options.end()) {
- args.options.erase(ait);
- FileOut::setDryRun(true);
- }
-
- QString licenseComment;
- ait = args.options.find(u"license-file"_s);
- if (ait != args.options.end()) {
- QFile licenseFile(ait.value().toString());
- args.options.erase(ait);
- if (licenseFile.open(QIODevice::ReadOnly)) {
- licenseComment = QString::fromUtf8(licenseFile.readAll());
- } else {
- errorPrint(QStringLiteral("Could not open the file \"%1\" containing the license heading: %2").
- arg(QDir::toNativeSeparators(licenseFile.fileName()), licenseFile.errorString()));
- return EXIT_FAILURE;
- }
- }
-
- QString outputDirectory = u"out"_s;
- ait = args.options.find(u"output-directory"_s);
- if (ait != args.options.end()) {
- outputDirectory = ait.value().toString();
- args.options.erase(ait);
- }
-
- if (!QDir(outputDirectory).exists()) {
- if (!QDir().mkpath(outputDirectory)) {
+ if (!QDir(commonOptions.outputDirectory).exists()) {
+ if (!QDir().mkpath(commonOptions.outputDirectory)) {
qCWarning(lcShiboken).noquote().nospace()
- << "Can't create output directory: " << QDir::toNativeSeparators(outputDirectory);
+ << "Can't create output directory: "
+ << QDir::toNativeSeparators(commonOptions.outputDirectory);
return EXIT_FAILURE;
}
}
// Create and set-up API Extractor
- ApiExtractor extractor;
- extractor.setLogDirectory(outputDirectory);
- ait = args.options.find(skipDeprecatedOption());
- if (ait != args.options.end()) {
- extractor.setSkipDeprecated(true);
- args.options.erase(ait);
- }
-
- ait = args.options.find(u"silent"_s);
- if (ait != args.options.end()) {
- extractor.setSilent(true);
- args.options.erase(ait);
- } else {
- ait = args.options.find(u"debug-level"_s);
- if (ait != args.options.end()) {
- const QString value = ait.value().toString();
- if (!ReportHandler::setDebugLevelFromArg(value)) {
- errorPrint(u"Invalid debug level: "_s + value);
- return EXIT_FAILURE;
- }
- args.options.erase(ait);
- }
- }
- ait = args.options.find(u"no-suppress-warnings"_s);
- if (ait != args.options.end()) {
- args.options.erase(ait);
- extractor.setSuppressWarnings(false);
- }
- ait = args.options.find(apiVersionOption());
- if (ait != args.options.end()) {
- const QStringList &versions = ait.value().toStringList();
- args.options.erase(ait);
- for (const QString &fullVersion : versions) {
- QStringList parts = fullVersion.split(u',');
- QString package;
- QString version;
- package = parts.size() == 1 ? u"*"_s : parts.constFirst();
- version = parts.constLast();
- if (!extractor.setApiVersion(package, version)) {
- errorPrint(msgInvalidVersion(package, version));
- return EXIT_FAILURE;
- }
+ extractor.setLogDirectory(commonOptions.outputDirectory);
+
+ if (commonOptions.typeSystemFileName.isEmpty() && commonOptions.headers.isEmpty()) {
+ if (options.positionalArguments.size() < 2) {
+ errorPrint(u"Insufficient positional arguments, specify header-file and typesystem-file."_s,
+ argV);
+ std::cout << '\n';
+ printUsage();
+ return EXIT_FAILURE;
}
- }
-
- ait = args.options.find(dropTypeEntriesOption());
- if (ait != args.options.end()) {
- extractor.setDropTypeEntries(ait.value().toStringList());
- args.options.erase(ait);
- }
-
- ait = args.options.find(keywordsOption());
- if (ait != args.options.end()) {
- extractor.setTypesystemKeywords(ait.value().toStringList());
- args.options.erase(ait);
- }
- ait = args.options.find(typesystemPathOption());
- if (ait != args.options.end()) {
- extractor.addTypesystemSearchPath(ait.value().toStringList());
- args.options.erase(ait);
+ commonOptions.typeSystemFileName = options.positionalArguments.takeLast();
+ commonOptions.headers = options.positionalArguments;
}
- ait = args.options.find(clangOptionsOption());
- if (ait != args.options.end()) {
- extractor.setClangOptions(ait.value().toStringList());
- args.options.erase(ait);
- }
-
- parseIncludePathOption(includePathOption(), HeaderType::Standard,
- args, extractor);
- parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework,
- args, extractor);
- parseIncludePathOption(systemIncludePathOption(), HeaderType::System,
- args, extractor);
-
- if (args.positionalArguments.size() < 2) {
- errorPrint(u"Insufficient positional arguments, specify header-file and typesystem-file."_s);
- std::cout << '\n';
- printUsage();
- return EXIT_FAILURE;
- }
-
- const QString typeSystemFileName = args.positionalArguments.takeLast();
- QString messagePrefix = QFileInfo(typeSystemFileName).baseName();
+ QString messagePrefix = QFileInfo(commonOptions.typeSystemFileName).baseName();
if (messagePrefix.startsWith(u"typesystem_"))
messagePrefix.remove(0, 11);
ReportHandler::setPrefix(u'(' + messagePrefix + u')');
QFileInfoList cppFileNames;
- for (const QString &cppFileName : qAsConst(args.positionalArguments)) {
+ for (const QString &cppFileName : std::as_const(commonOptions.headers)) {
const QFileInfo cppFileNameFi(cppFileName);
if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) {
- errorPrint(u'"' + cppFileName + u"\" does not exist."_s);
+ errorPrint(u'"' + cppFileName + u"\" does not exist."_s, argV);
return EXIT_FAILURE;
}
cppFileNames.append(cppFileNameFi);
}
- // Pass option to all generators (Cpp/Header generator have the same options)
- for (ait = args.options.begin(); ait != args.options.end(); ) {
- bool found = false;
- for (const GeneratorPtr &generator : qAsConst(generators))
- found |= generator->handleOption(ait.key(), ait.value().toString());
- if (found)
- ait = args.options.erase(ait);
- else
- ++ait;
- }
+ optionParser.process(&options);
+ optionParser.clear();
- ait = args.options.find(languageLevelOption());
- if (ait != args.options.end()) {
- const QByteArray languageLevelBA = ait.value().toString().toLatin1();
- args.options.erase(ait);
- const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
- if (level == LanguageLevel::Default) {
- std::cout << "Invalid argument for language level: \""
- << languageLevelBA.constData() << "\"\n" << helpHint;
- return EXIT_FAILURE;
- }
- extractor.setLanguageLevel(level);
- }
-
- /* Make sure to remove the project file's arguments (if any) and
- * --project-file, also the arguments of each generator before
- * checking if there isn't any existing arguments in argsHandler.
- */
- args.options.remove(u"project-file"_s);
- for (auto it = projectFileArguments.options.cbegin(), end = projectFileArguments.options.cend();
- it != end; ++it) {
- args.options.remove(it.key());
- }
-
- if (!args.options.isEmpty()) {
- errorPrint(msgLeftOverArguments(args.options));
+ if (!options.boolOptions.isEmpty() || !options.valueOptions.isEmpty()) {
+ errorPrint(msgLeftOverArguments(options.msgUnprocessedOptions(), argV), argV);
std::cout << helpHint;
return EXIT_FAILURE;
}
- if (typeSystemFileName.isEmpty()) {
+ if (commonOptions.typeSystemFileName.isEmpty()) {
std::cout << "You must specify a Type System file." << std::endl << helpHint;
return EXIT_FAILURE;
}
extractor.setCppFileNames(cppFileNames);
- extractor.setTypeSystem(typeSystemFileName);
+ extractor.setTypeSystem(commonOptions.typeSystemFileName);
ApiExtractorFlags apiExtractorFlags;
if (generators.constFirst()->usePySideExtensions())
@@ -678,7 +363,7 @@ int shibokenMain(int argc, char *argv[])
const std::optional<ApiExtractorResult> apiOpt = extractor.run(apiExtractorFlags);
if (!apiOpt.has_value()) {
- errorPrint(u"Error running ApiExtractor."_s);
+ errorPrint(u"Error running ApiExtractor."_s, argV);
return EXIT_FAILURE;
}
@@ -691,32 +376,59 @@ int shibokenMain(int argc, char *argv[])
<< "\n\nType datase:\n" << *TypeDatabase::instance();
}
- for (const GeneratorPtr &g : qAsConst(generators)) {
- g->setOutputDirectory(outputDirectory);
- g->setLicenseComment(licenseComment);
- ReportHandler::startProgress(QByteArray("Running ") + g->name() + "...");
+ if (commonOptions.printBuiltinTypes)
+ TypeDatabase::instance()->formatBuiltinTypes(qInfo());
+
+ for (const GeneratorPtr &g : std::as_const(generators)) {
+ g->setOutputDirectory(commonOptions.outputDirectory);
+ g->setLicenseComment(commonOptions.licenseComment);
+ ReportHandler::startProgress("Ran "_ba + g->name() + '.');
const bool ok = g->setup(apiOpt.value()) && g->generate();
ReportHandler::endProgress();
if (!ok) {
errorPrint(u"Error running generator: "_s
- + QLatin1StringView(g->name()) + u'.');
+ + QLatin1StringView(g->name()) + u'.', argV);
return EXIT_FAILURE;
}
}
+ if (commonOptions.logUnmatched)
+ TypeDatabase::instance()->logUnmatched();
+
const QByteArray doneMessage = ReportHandler::doneMessage();
std::cout << doneMessage.constData() << std::endl;
return EXIT_SUCCESS;
}
+#ifndef Q_OS_WIN
+
+static inline QString argvToString(const char *arg)
+{
+ return QString::fromLocal8Bit(arg);
+}
+
int main(int argc, char *argv[])
+#else
+
+static inline QString argvToString(const wchar_t *arg)
+{
+ return QString::fromWCharArray(arg);
+}
+
+int wmain(int argc, wchar_t *argv[])
+#endif
{
int ex = EXIT_SUCCESS;
+
+ QStringList argV;
+ argV.reserve(argc - 1);
+ std::transform(argv + 1, argv + argc, std::back_inserter(argV), argvToString);
+
try {
- ex = shibokenMain(argc, argv);
+ ex = shibokenMain(argV);
} catch (const std::exception &e) {
- std::cerr << e.what() << std::endl;
+ std::cerr << appName << " error: " << e.what() << std::endl;
ex = EXIT_FAILURE;
}
return ex;
diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
index 9e31b9366..2797ff254 100644
--- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
@@ -2,8 +2,10 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qtdocgenerator.h"
+#include "generatorcontext.h"
#include "codesnip.h"
#include "exception.h"
+#include "abstractmetaargument.h"
#include "apiextractorresult.h"
#include "qtxmltosphinx.h"
#include "rstformat.h"
@@ -13,6 +15,7 @@
#include <abstractmetafield.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
+#include "abstractmetalang_helpers.h"
#include <fileout.h>
#include <messages.h>
#include <modifications.h>
@@ -23,6 +26,8 @@
#include <functiontypeentry.h>
#include <enumtypeentry.h>
#include <complextypeentry.h>
+#include <flagstypeentry.h>
+#include <primitivetypeentry.h>
#include <qtdocparser.h>
#include <doxygenparser.h>
@@ -31,20 +36,84 @@
#include <QtCore/QTextStream>
#include <QtCore/QFile>
#include <QtCore/QDir>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QSet>
#include <algorithm>
#include <limits>
using namespace Qt::StringLiterals;
-static inline QString additionalDocumentationOption() { return QStringLiteral("additional-documentation"); }
+static inline QString classScope(const AbstractMetaClassCPtr &metaClass)
+{
+ return metaClass->fullName();
+}
+
+struct DocPackage
+{
+ QStringList classPages;
+ QStringList decoratorPages;
+ AbstractMetaFunctionCList globalFunctions;
+ AbstractMetaEnumList globalEnums;
+};
+
+struct DocGeneratorOptions
+{
+ QtXmlToSphinxParameters parameters;
+ QString extraSectionDir;
+ QString additionalDocumentationList;
+ QString inheritanceFile;
+ bool doxygen = false;
+ bool inheritanceDiagram = true;
+};
+
+struct GeneratorDocumentation
+{
+ struct Property
+ {
+ QString name;
+ Documentation documentation;
+ AbstractMetaType type;
+ AbstractMetaFunctionCPtr getter;
+ AbstractMetaFunctionCPtr setter;
+ AbstractMetaFunctionCPtr reset;
+ AbstractMetaFunctionCPtr notify;
+ };
+
+ AbstractMetaFunctionCList allFunctions;
+ AbstractMetaFunctionCList tocNormalFunctions; // Index lists
+ AbstractMetaFunctionCList tocVirtuals;
+ AbstractMetaFunctionCList tocSignalFunctions;
+ AbstractMetaFunctionCList tocSlotFunctions;
+ AbstractMetaFunctionCList tocStaticFunctions;
+
+ QList<Property> properties;
+};
+
+static bool operator<(const GeneratorDocumentation::Property &lhs,
+ const GeneratorDocumentation::Property &rhs)
+{
+ return lhs.name < rhs.name;
+}
+
+static QString propertyRefTarget(const QString &name)
+{
+ QString result = name;
+ // For sphinx referencing, disambiguate the target from the getter name
+ // by appending an invisible "Hangul choseong filler" character.
+ result.append(QChar(0x115F));
+ return result;
+}
+
+constexpr auto additionalDocumentationOption = "additional-documentation"_L1;
-static inline QString none() { return QStringLiteral("None"); }
+constexpr auto none = "None"_L1;
static bool shouldSkip(const AbstractMetaFunctionCPtr &func)
{
- // Constructors go to separate section
- if (DocParser::skipForQuery(func) || func->isConstructor())
+ if (DocParser::skipForQuery(func))
return true;
// Search a const clone (QImage::bits() vs QImage::bits() const)
@@ -77,22 +146,161 @@ static bool shouldSkip(const AbstractMetaFunctionCPtr &func)
static bool functionSort(const AbstractMetaFunctionCPtr &func1, const AbstractMetaFunctionCPtr &func2)
{
- return func1->name() < func2->name();
+ const bool ctor1 = func1->isConstructor();
+ if (ctor1 != func2->isConstructor())
+ return ctor1;
+ const QString &name1 = func1->name();
+ const QString &name2 = func2->name();
+ if (name1 != name2)
+ return name1 < name2;
+ return func1->arguments().size() < func2->arguments().size();
}
-static inline QVersionNumber versionOf(const TypeEntry *te)
+static inline QVersionNumber versionOf(const TypeEntryCPtr &te)
{
if (te) {
const auto version = te->version();
if (!version.isNull() && version > QVersionNumber(0, 0))
return version;
}
- return QVersionNumber();
+ return {};
+}
+
+struct docRef
+{
+ explicit docRef(const char *kind, QAnyStringView name) :
+ m_kind(kind), m_name(name) {}
+
+ const char *m_kind;
+ QAnyStringView m_name;
+};
+
+static TextStream &operator<<(TextStream &s, const docRef &dr)
+{
+ s << ':' << dr.m_kind << ":`" << dr.m_name << '`';
+ return s;
+}
+
+static QString fileNameToTocEntry(const QString &fileName)
+{
+ constexpr auto rstSuffix = ".rst"_L1;
+
+ QString result = fileName;
+ if (result.endsWith(rstSuffix))
+ result.chop(rstSuffix.size()); // Remove the .rst extension
+ // skip namespace if necessary
+ auto lastDot = result.lastIndexOf(u'.');
+ if (lastDot != -1)
+ result.remove(0, lastDot + 1);
+ return result;
+}
+
+static void readExtraDoc(const QFileInfo &fi,
+ const QString &moduleName,
+ const QString &outputDir,
+ DocPackage *docPackage, QStringList *extraTocEntries)
+{
+ // Strip to "Property.rst" in output directory
+ const QString newFileName = fi.fileName().mid(moduleName.size() + 1);
+ QFile sourceFile(fi.absoluteFilePath());
+ if (!sourceFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotOpenForReading(sourceFile)));
+ return;
+ }
+ const QByteArray contents = sourceFile.readAll();
+ sourceFile.close();
+ QFile targetFile(outputDir + u'/' + newFileName);
+ if (!targetFile.open(QIODevice::WriteOnly|QIODevice::Text)) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotOpenForWriting(targetFile)));
+ return;
+ }
+ targetFile.write(contents);
+ if (contents.contains("decorator::"))
+ docPackage->decoratorPages.append(newFileName);
+ else
+ docPackage->classPages.append(newFileName);
+ extraTocEntries->append(fileNameToTocEntry(newFileName));
+}
+
+// Format a short documentation reference (automatically dropping the prefix
+// by using '~'), usable for property/attributes ("attr").
+struct shortDocRef
+{
+ explicit shortDocRef(const char *kind, QAnyStringView name) :
+ m_kind(kind), m_name(name) {}
+
+ const char *m_kind;
+ QAnyStringView m_name;
+};
+
+static TextStream &operator<<(TextStream &s, const shortDocRef &sdr)
+{
+ s << ':' << sdr.m_kind << ":`~" << sdr.m_name << '`';
+ return s;
+}
+
+struct functionRef : public docRef
+{
+ explicit functionRef(QAnyStringView name) : docRef("meth", name) {}
+};
+
+struct classRef : public shortDocRef
+{
+ explicit classRef(QAnyStringView name) : shortDocRef("class", name) {}
+};
+
+struct propRef : public shortDocRef // Attribute/property (short) reference
+{
+ explicit propRef(const QString &target) :
+ shortDocRef("attr", target) {}
+};
+
+struct headline
+{
+ explicit headline(QAnyStringView title, char underLineChar = '-') :
+ m_title(title), m_underLineChar(underLineChar) {}
+
+ QAnyStringView m_title;
+ char m_underLineChar;
+};
+
+static TextStream &operator<<(TextStream &s, const headline &h)
+{
+ s << h.m_title << '\n' << Pad(h.m_underLineChar, h.m_title.size()) << "\n\n";
+ return s;
+}
+
+struct pyClass
+{
+ explicit pyClass(QAnyStringView name) : m_name(name) {}
+
+ QAnyStringView m_name;
+};
+
+static TextStream &operator<<(TextStream &s, pyClass c)
+{
+ s << ".. py:class:: " << c.m_name << "\n\n";
+ return s;
}
+struct currentModule
+{
+ explicit currentModule(QAnyStringView module) : m_module(module) {}
+
+ QAnyStringView m_module;
+};
+
+static TextStream &operator<<(TextStream &s, const currentModule &m)
+{
+ s << ".. currentmodule:: " << m.m_module << "\n\n\n";
+ return s;
+}
+
+DocGeneratorOptions QtDocGenerator::m_options;
+
QtDocGenerator::QtDocGenerator()
{
- m_parameters.snippetComparison =
+ m_options.parameters.snippetComparison =
ReportHandler::debugLevel() >= ReportHandler::FullDebug;
}
@@ -103,7 +311,7 @@ QString QtDocGenerator::fileNameSuffix()
return u".rst"_s;
}
-bool QtDocGenerator::shouldGenerate(const TypeEntry *te) const
+bool QtDocGenerator::shouldGenerate(const TypeEntryCPtr &te) const
{
return Generator::shouldGenerate(te)
&& te->type() != TypeEntry::SmartPointerType;
@@ -117,28 +325,23 @@ QString QtDocGenerator::fileNameForContext(const GeneratorContext &context) cons
}
void QtDocGenerator::writeFormattedBriefText(TextStream &s, const Documentation &doc,
- const AbstractMetaClass *metaclass) const
+ const QString &scope) const
{
- writeFormattedText(s, doc.brief(), doc.format(), metaclass);
+ writeFormattedText(s, doc.brief(), doc.format(), scope);
}
void QtDocGenerator::writeFormattedDetailedText(TextStream &s, const Documentation &doc,
- const AbstractMetaClass *metaclass) const
+ const QString &scope) const
{
- writeFormattedText(s, doc.detailed(), doc.format(), metaclass);
+ writeFormattedText(s, doc.detailed(), doc.format(), scope);
}
void QtDocGenerator::writeFormattedText(TextStream &s, const QString &doc,
Documentation::Format format,
- const AbstractMetaClass *metaClass) const
+ const QString &scope) const
{
- QString metaClassName;
-
- if (metaClass)
- metaClassName = metaClass->fullName();
-
if (format == Documentation::Native) {
- QtXmlToSphinx x(this, m_parameters, doc, metaClassName);
+ QtXmlToSphinx x(this, m_options.parameters, doc, scope);
s << x;
} else {
const auto lines = QStringView{doc}.split(u'\n');
@@ -162,50 +365,71 @@ void QtDocGenerator::writeFormattedText(TextStream &s, const QString &doc,
s << '\n';
}
-static void writeInheritedByList(TextStream& s, const AbstractMetaClass* metaClass,
+static void writeInheritanceList(TextStream &s, const AbstractMetaClassCList& classes,
+ const char *label)
+{
+ s << "**" << label << ":** ";
+ for (qsizetype i = 0, size = classes.size(); i < size; ++i) {
+ if (i > 0)
+ s << ", ";
+ s << classRef(classes.at(i)->fullName());
+ }
+ s << "\n\n";
+}
+
+static void writeInheritedByList(TextStream &s, const AbstractMetaClassCPtr &metaClass,
const AbstractMetaClassCList& allClasses)
{
AbstractMetaClassCList res;
- for (auto c : allClasses) {
- if (c != metaClass && c->inheritsFrom(metaClass))
+ for (const auto &c : allClasses) {
+ if (c != metaClass && inheritsFrom(c, metaClass))
res << c;
}
- if (res.isEmpty())
- return;
+ if (!res.isEmpty())
+ writeInheritanceList(s, res, "Inherited by");
+}
+
+static void writeInheritedFromList(TextStream &s, const AbstractMetaClassCPtr &metaClass)
+{
+ AbstractMetaClassCList res;
- s << "**Inherited by:** ";
- QStringList classes;
- for (auto c : qAsConst(res))
- classes << u":ref:`"_s + c->name() + u'`';
- s << classes.join(u", "_s) << "\n\n";
+ recurseClassHierarchy(metaClass, [&res, metaClass](const AbstractMetaClassCPtr &c) {
+ if (c.get() != metaClass.get())
+ res.append(c);
+ return false;
+ });
+
+ if (!res.isEmpty())
+ writeInheritanceList(s, res, "Inherits from");
}
void QtDocGenerator::generateClass(TextStream &s, const GeneratorContext &classContext)
{
- const AbstractMetaClass *metaClass = classContext.metaClass();
+ AbstractMetaClassCPtr metaClass = classContext.metaClass();
qCDebug(lcShibokenDoc).noquote().nospace() << "Generating Documentation for " << metaClass->fullName();
- m_packages[metaClass->package()] << fileNameForContext(classContext);
+ m_packages[metaClass->package()].classPages << fileNameForContext(classContext);
m_docParser->setPackageName(metaClass->package());
- m_docParser->fillDocumentation(const_cast<AbstractMetaClass*>(metaClass));
+ m_docParser->fillDocumentation(std::const_pointer_cast<AbstractMetaClass>(metaClass));
- QString className = metaClass->name();
- s << ".. _" << className << ":" << "\n\n";
- s << ".. currentmodule:: " << metaClass->package() << "\n\n\n";
-
- s << className << '\n';
- s << Pad('*', className.size()) << "\n\n";
+ s << currentModule(metaClass->package()) << pyClass(metaClass->name());
+ Indentation indent(s);
auto documentation = metaClass->documentation();
+ const QString scope = classScope(metaClass);
if (documentation.hasBrief())
- writeFormattedBriefText(s, documentation, metaClass);
-
- s << ".. inheritance-diagram:: " << metaClass->fullName()<< '\n'
- << " :parts: 2\n\n";
- // TODO: This would be a parameter in the future...
+ writeFormattedBriefText(s, documentation, scope);
+ if (!metaClass->baseClasses().isEmpty()) {
+ if (m_options.inheritanceDiagram) {
+ s << ".. inheritance-diagram:: " << metaClass->fullName()<< '\n'
+ << " :parts: 2\n\n";
+ } else {
+ writeInheritedFromList(s, metaClass);
+ }
+ }
writeInheritedByList(s, metaClass, api().classes());
@@ -215,123 +439,113 @@ void QtDocGenerator::generateClass(TextStream &s, const GeneratorContext &classC
if (metaClass->attributes().testFlag(AbstractMetaClass::Deprecated))
s << rstDeprecationNote("class");
- writeFunctionList(s, metaClass);
-
- //Function list
- auto functionList = metaClass->functions();
- std::sort(functionList.begin(), functionList.end(), functionSort);
+ const GeneratorDocumentation doc = generatorDocumentation(metaClass);
- s << "\nDetailed Description\n"
- "--------------------\n\n"
- << ".. _More:\n";
+ if (!doc.allFunctions.isEmpty() || !doc.properties.isEmpty()) {
+ s << '\n' << headline("Synopsis");
+ writePropertyToc(s, doc);
+ writeFunctionToc(s, u"Methods"_s, doc.tocNormalFunctions);
+ writeFunctionToc(s, u"Virtual methods"_s, doc.tocVirtuals);
+ writeFunctionToc(s, u"Slots"_s, doc.tocSlotFunctions);
+ writeFunctionToc(s, u"Signals"_s, doc.tocSignalFunctions);
+ writeFunctionToc(s, u"Static functions"_s, doc.tocStaticFunctions);
+ }
- writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, nullptr);
- if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, nullptr))
- writeFormattedDetailedText(s, documentation, metaClass);
+ s << "\n.. note::\n"
+ " This documentation may contain snippets that were automatically\n"
+ " translated from C++ to Python. We always welcome contributions\n"
+ " to the snippet translation. If you see an issue with the\n"
+ " translation, you can also let us know by creating a ticket on\n"
+ " https:/bugreports.qt.io/projects/PYSIDE\n\n";
- if (!metaClass->isNamespace())
- writeConstructors(s, metaClass);
- writeEnums(s, metaClass);
- if (!metaClass->isNamespace())
- writeFields(s, metaClass);
+ s << '\n' << headline("Detailed Description") << ".. _More:\n";
+ writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass);
+ if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass))
+ writeFormattedDetailedText(s, documentation, scope);
+ writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass);
- QStringList uniqueFunctions;
- for (const auto &func : qAsConst(functionList)) {
- if (shouldSkip(func))
- continue;
+ writeEnums(s, metaClass->enums(), scope);
- if (func->isStatic())
- s << ".. staticmethod:: ";
- else
- s << ".. method:: ";
+ if (!doc.properties.isEmpty())
+ writeProperties(s, doc, metaClass);
- writeFunction(s, metaClass, func, !uniqueFunctions.contains(func->name()));
- uniqueFunctions.append(func->name());
- }
+ if (!metaClass->isNamespace())
+ writeFields(s, metaClass);
- writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass, nullptr);
+ writeFunctions(s, doc.allFunctions, metaClass, scope);
}
-void QtDocGenerator::writeFunctionList(TextStream& s, const AbstractMetaClass* cppClass)
+void QtDocGenerator::writeFunctionToc(TextStream &s, const QString &title,
+ const AbstractMetaFunctionCList &functions)
{
- QStringList functionList;
- QStringList virtualList;
- QStringList signalList;
- QStringList slotList;
- QStringList staticFunctionList;
-
- const auto &classFunctions = cppClass->functions();
- for (const auto &func : classFunctions) {
- if (shouldSkip(func))
- continue;
-
- QString className;
- if (!func->isConstructor())
- className = cppClass->fullName() + u'.';
- else if (func->implementingClass() && func->implementingClass()->enclosingClass())
- className = func->implementingClass()->enclosingClass()->fullName() + u'.';
- QString funcName = getFuncName(func);
-
- QString str = u"def :meth:`"_s;
-
- str += funcName;
- str += u'<';
- if (!funcName.startsWith(className))
- str += className;
- str += funcName;
- str += u">` ("_s;
- str += parseArgDocStyle(cppClass, func);
- str += u')';
-
- if (func->isStatic())
- staticFunctionList << str;
- else if (func->isVirtual())
- virtualList << str;
- else if (func->isSignal())
- signalList << str;
- else if (func->isSlot())
- slotList << str;
- else
- functionList << str;
+ if (!functions.isEmpty()) {
+ s << headline(title, '^')
+ << ".. container:: function_list\n\n" << indent;
+ // Functions are sorted by the Metabuilder; erase overloads
+ QStringList toc;
+ toc.reserve(functions.size());
+ std::transform(functions.cbegin(), functions.end(),
+ std::back_inserter(toc), getFuncName);
+ toc.erase(std::unique(toc.begin(), toc.end()), toc.end());
+ for (const auto &func : toc)
+ s << "* def " << functionRef(func) << '\n';
+ s << outdent << "\n\n";
}
+}
- if (!functionList.isEmpty() || !staticFunctionList.isEmpty()) {
- QtXmlToSphinx::Table functionTable;
-
- s << "\nSynopsis\n--------\n\n";
+void QtDocGenerator::writePropertyToc(TextStream &s,
+ const GeneratorDocumentation &doc)
+{
+ if (doc.properties.isEmpty())
+ return;
- writeFunctionBlock(s, u"Functions"_s, functionList);
- writeFunctionBlock(s, u"Virtual functions"_s, virtualList);
- writeFunctionBlock(s, u"Slots"_s, slotList);
- writeFunctionBlock(s, u"Signals"_s, signalList);
- writeFunctionBlock(s, u"Static functions"_s, staticFunctionList);
+ s << headline("Properties", '^')
+ << ".. container:: function_list\n\n" << indent;
+ for (const auto &prop : doc.properties) {
+ s << "* " << propRef(propertyRefTarget(prop.name));
+ if (prop.documentation.hasBrief())
+ s << " - " << prop.documentation.brief();
+ s << '\n';
}
+ s << outdent << "\n\n";
}
-void QtDocGenerator::writeFunctionBlock(TextStream& s, const QString& title, QStringList& functions)
+void QtDocGenerator::writeProperties(TextStream &s,
+ const GeneratorDocumentation &doc,
+ const AbstractMetaClassCPtr &cppClass) const
{
- if (!functions.isEmpty()) {
- s << title << '\n'
- << Pad('^', title.size()) << '\n';
-
- std::sort(functions.begin(), functions.end());
-
- s << ".. container:: function_list\n\n";
- Indentation indentation(s);
- for (const QString &func : qAsConst(functions))
- s << "* " << func << '\n';
- s << "\n\n";
+ s << "\n.. note:: Properties can be used directly when "
+ << "``from __feature__ import true_property`` is used or via accessor "
+ << "functions otherwise.\n\n";
+
+ const QString scope = classScope(cppClass);
+ for (const auto &prop : doc.properties) {
+ const QString type = translateToPythonType(prop.type, cppClass, /* createRef */ false);
+ s << ".. py:property:: " << propertyRefTarget(prop.name)
+ << "\n :type: " << type << "\n\n\n";
+ if (!prop.documentation.isEmpty())
+ writeFormattedText(s, prop.documentation.detailed(), Documentation::Native, scope);
+ s << "**Access functions:**\n";
+ if (prop.getter)
+ s << " * " << functionRef(prop.getter->name()) << '\n';
+ if (prop.setter)
+ s << " * " << functionRef(prop.setter->name()) << '\n';
+ if (prop.reset)
+ s << " * " << functionRef(prop.reset->name()) << '\n';
+ if (prop.notify)
+ s << " * Signal " << functionRef(prop.notify->name()) << '\n';
+ s << '\n';
}
}
-void QtDocGenerator::writeEnums(TextStream& s, const AbstractMetaClass* cppClass) const
+void QtDocGenerator::writeEnums(TextStream &s, const AbstractMetaEnumList &enums,
+ const QString &scope) const
{
- static const QString section_title = u".. attribute:: "_s;
-
- for (const AbstractMetaEnum &en : cppClass->enums()) {
- s << section_title << cppClass->fullName() << '.' << en.name() << "\n\n";
- writeFormattedDetailedText(s, en.documentation(), cppClass);
+ for (const AbstractMetaEnum &en : enums) {
+ s << pyClass(en.name());
+ Indentation indent(s);
+ writeFormattedDetailedText(s, en.documentation(), scope);
const auto version = versionOf(en.typeEntry());
if (!version.isNull())
s << rstVersionAdded(version);
@@ -339,76 +553,20 @@ void QtDocGenerator::writeEnums(TextStream& s, const AbstractMetaClass* cppClass
}
-void QtDocGenerator::writeFields(TextStream& s, const AbstractMetaClass* cppClass) const
+void QtDocGenerator::writeFields(TextStream &s, const AbstractMetaClassCPtr &cppClass) const
{
- static const QString section_title = u".. attribute:: "_s;
+ constexpr auto section_title = ".. attribute:: "_L1;
+ const QString scope = classScope(cppClass);
for (const AbstractMetaField &field : cppClass->fields()) {
s << section_title << cppClass->fullName() << "." << field.name() << "\n\n";
- writeFormattedDetailedText(s, field.documentation(), cppClass);
- }
-}
-
-void QtDocGenerator::writeConstructors(TextStream& s, const AbstractMetaClass* cppClass) const
-{
- static const QString sectionTitle = u".. class:: "_s;
-
- auto lst = cppClass->queryFunctions(FunctionQueryOption::AnyConstructor
- | FunctionQueryOption::Visible);
- for (int i = lst.size() - 1; i >= 0; --i) {
- if (lst.at(i)->isModifiedRemoved() || lst.at(i)->functionType() == AbstractMetaFunction::MoveConstructorFunction)
- lst.removeAt(i);
- }
-
- bool first = true;
- QHash<QString, AbstractMetaArgument> arg_map;
-
- if (lst.isEmpty()) {
- s << sectionTitle << cppClass->fullName();
- } else {
- QByteArray pad;
- for (const auto &func : qAsConst(lst)) {
- s << pad;
- if (first) {
- first = false;
- s << sectionTitle;
- pad = QByteArray(sectionTitle.size(), ' ');
- }
- s << functionSignature(cppClass, func) << "\n\n";
-
- const auto version = versionOf(func->typeEntry());
- if (!version.isNull())
- s << pad << rstVersionAdded(version);
- if (func->isDeprecated())
- s << pad << rstDeprecationNote("constructor");
-
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument &arg : arguments) {
- if (!arg_map.contains(arg.name())) {
- arg_map.insert(arg.name(), arg);
- }
- }
- }
+ writeFormattedDetailedText(s, field.documentation(), scope);
}
-
- s << '\n';
-
- for (auto it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) {
- s.indent(2);
- writeParameterType(s, cppClass, it.value());
- s.outdent(2);
- }
-
- s << '\n';
-
- for (const auto &func : qAsConst(lst))
- writeFormattedDetailedText(s, func->documentation(), cppClass);
}
-QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* /* cppClass */,
- const AbstractMetaFunctionCPtr &func)
+QString QtDocGenerator::formatArgs(const AbstractMetaFunctionCPtr &func)
{
- QString ret;
+ QString ret = u"("_s;
int optArgs = 0;
const AbstractMetaArgumentList &arguments = func->arguments();
@@ -437,19 +595,19 @@ QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* /* cppClass */
|| defValue.startsWith(u"QList")) {
defValue = u"list()"_s;
} else if (defValue == u"QVariant()") {
- defValue = none();
+ defValue = none;
} else {
defValue.replace(u"::"_s, u"."_s);
if (defValue == u"nullptr")
- defValue = none();
+ defValue = none;
else if (defValue == u"0" && arg.type().isObject())
- defValue = none();
+ defValue = none;
}
ret += u'=' + defValue;
}
}
- ret += QString(optArgs, u']');
+ ret += QString(optArgs, u']') + u')';
return ret;
}
@@ -459,12 +617,10 @@ void QtDocGenerator::writeDocSnips(TextStream &s,
TypeSystem::Language language)
{
Indentation indentation(s);
- QStringList invalidStrings;
+ static const QStringList invalidStrings{u"*"_s, u"//"_s, u"/*"_s, u"*/"_s};
const static QString startMarkup = u"[sphinx-begin]"_s;
const static QString endMarkup = u"[sphinx-end]"_s;
- invalidStrings << u"*"_s << u"//"_s << u"/*"_s << u"*/"_s;
-
for (const CodeSnip &snip : codeSnips) {
if ((snip.position != position) ||
!(snip.language & language))
@@ -472,8 +628,8 @@ void QtDocGenerator::writeDocSnips(TextStream &s,
QString code = snip.code();
while (code.contains(startMarkup) && code.contains(endMarkup)) {
- int startBlock = code.indexOf(startMarkup) + startMarkup.size();
- int endBlock = code.indexOf(endMarkup);
+ const auto startBlock = code.indexOf(startMarkup) + startMarkup.size();
+ const auto endBlock = code.indexOf(endMarkup);
if ((startBlock == -1) || (endBlock == -1))
break;
@@ -481,10 +637,10 @@ void QtDocGenerator::writeDocSnips(TextStream &s,
QString codeBlock = code.mid(startBlock, endBlock - startBlock);
const QStringList rows = codeBlock.split(u'\n');
int currentRow = 0;
- int offset = 0;
+ qsizetype offset = 0;
for (QString row : rows) {
- for (const QString &invalidString : qAsConst(invalidStrings))
+ for (const QString &invalidString : std::as_const(invalidStrings))
row.remove(invalidString);
if (row.trimmed().size() == 0) {
@@ -513,97 +669,127 @@ void QtDocGenerator::writeDocSnips(TextStream &s,
}
}
-bool QtDocGenerator::writeInjectDocumentation(TextStream& s,
- TypeSystem::DocModificationMode mode,
- const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func)
+bool QtDocGenerator::writeDocModifications(TextStream &s,
+ const DocModificationList &mods,
+ TypeSystem::DocModificationMode mode,
+ const QString &scope) const
{
- Indentation indentation(s);
bool didSomething = false;
-
- const DocModificationList &mods = cppClass->typeEntry()->docModifications();
for (const DocModification &mod : mods) {
if (mod.mode() == mode) {
- bool modOk = func ? mod.signature() == func->minimalSignature() : mod.signature().isEmpty();
-
- if (modOk) {
- Documentation::Format fmt;
-
- if (mod.format() == TypeSystem::NativeCode)
- fmt = Documentation::Native;
- else if (mod.format() == TypeSystem::TargetLangCode)
- fmt = Documentation::Target;
- else
- continue;
-
- writeFormattedText(s, mod.code(), fmt, cppClass);
+ switch (mod.format()) {
+ case TypeSystem::NativeCode:
+ writeFormattedText(s, mod.code(), Documentation::Native, scope);
didSomething = true;
+ break;
+ case TypeSystem::TargetLangCode:
+ writeFormattedText(s, mod.code(), Documentation::Target, scope);
+ didSomething = true;
+ break;
+ default:
+ break;
}
}
}
+ return didSomething;
+}
+bool QtDocGenerator::writeInjectDocumentation(TextStream &s,
+ TypeSystem::DocModificationMode mode,
+ const AbstractMetaClassCPtr &cppClass) const
+{
+ const bool didSomething =
+ writeDocModifications(s, DocParser::getDocModifications(cppClass),
+ mode, classScope(cppClass));
s << '\n';
- // TODO: Deprecate the use of doc string on glue code.
+ // FIXME PYSIDE-7: Deprecate the use of doc string on glue code.
// This is pre "add-function" and "inject-documentation" tags.
const TypeSystem::CodeSnipPosition pos = mode == TypeSystem::DocModificationPrepend
? TypeSystem::CodeSnipPositionBeginning : TypeSystem::CodeSnipPositionEnd;
- if (func)
- writeDocSnips(s, func->injectedCodeSnips(), pos, TypeSystem::TargetLangCode);
- else
- writeDocSnips(s, cppClass->typeEntry()->codeSnips(), pos, TypeSystem::TargetLangCode);
+ writeDocSnips(s, cppClass->typeEntry()->codeSnips(), pos, TypeSystem::TargetLangCode);
return didSomething;
}
-QString QtDocGenerator::functionSignature(const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func)
+bool QtDocGenerator::writeInjectDocumentation(TextStream &s,
+ TypeSystem::DocModificationMode mode,
+ const DocModificationList &modifications,
+ const AbstractMetaFunctionCPtr &func,
+ const QString &scope) const
{
- QString funcName;
+ const bool didSomething = writeDocModifications(s, modifications, mode, scope);
+ s << '\n';
- funcName = cppClass->fullName();
- if (!func->isConstructor())
- funcName += u'.' + getFuncName(func);
+ // FIXME PYSIDE-7: Deprecate the use of doc string on glue code.
+ // This is pre "add-function" and "inject-documentation" tags.
+ const TypeSystem::CodeSnipPosition pos = mode == TypeSystem::DocModificationPrepend
+ ? TypeSystem::CodeSnipPositionBeginning : TypeSystem::CodeSnipPositionEnd;
+ writeDocSnips(s, func->injectedCodeSnips(), pos, TypeSystem::TargetLangCode);
+ return didSomething;
+}
- return funcName + u'(' + parseArgDocStyle(cppClass, func)
- + u')';
+static QString inline toRef(const QString &t)
+{
+ return ":class:`~"_L1 + t + u'`';
}
QString QtDocGenerator::translateToPythonType(const AbstractMetaType &type,
- const AbstractMetaClass* cppClass) const
+ const AbstractMetaClassCPtr &cppClass,
+ bool createRef) const
{
static const QStringList nativeTypes =
- {boolT(), floatT(), intT(), pyObjectT(), pyStrT()};
+ {boolT, floatT, intT, pyObjectT, pyStrT};
- const QString name = type.name();
+ QString name = type.name();
if (nativeTypes.contains(name))
return name;
- static const QMap<QString, QString> typeMap = {
- { cPyObjectT(), pyObjectT() },
- { qStringT(), pyStrT() },
- { u"uchar"_s, pyStrT() },
+ if (type.typeUsagePattern() == AbstractMetaType::PrimitivePattern) {
+ const auto &basicName = basicReferencedTypeEntry(type.typeEntry())->name();
+ if (AbstractMetaType::cppSignedIntTypes().contains(basicName)
+ || AbstractMetaType::cppUnsignedIntTypes().contains(basicName)) {
+ return intT;
+ }
+ if (AbstractMetaType::cppFloatTypes().contains(basicName))
+ return floatT;
+ }
+
+ static const QSet<QString> stringTypes = {
+ u"uchar"_s, u"std::string"_s, u"std::wstring"_s,
+ u"std::stringview"_s, u"std::wstringview"_s,
+ qStringT, u"QStringView"_s, u"QAnyStringView"_s, u"QUtf8StringView"_s
+ };
+ if (stringTypes.contains(name))
+ return pyStrT;
+
+ static const QHash<QString, QString> typeMap = {
+ { cPyObjectT, pyObjectT },
{ u"QStringList"_s, u"list of strings"_s },
- { qVariantT(), pyObjectT() },
- { u"quint32"_s, intT() },
- { u"uint32_t"_s, intT() },
- { u"quint64"_s, intT() },
- { u"qint64"_s, intT() },
- { u"size_t"_s, intT() },
- { u"int64_t"_s, intT() },
- { u"qreal"_s, floatT() }
+ { qVariantT, pyObjectT }
};
- const auto found = typeMap.find(name);
- if (found != typeMap.end())
+ const auto found = typeMap.constFind(name);
+ if (found != typeMap.cend())
return found.value();
- QString strType;
- if (type.isConstant() && name == u"char" && type.indirections() == 1) {
- strType = u"str"_s;
- } else if (name.startsWith(unsignedShortT())) {
- strType = intT();
- } else if (name.startsWith(unsignedT())) { // uint and ulong
- strType = intT();
- } else if (type.isContainer()) {
+ if (type.isFlags()) {
+ const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(type.typeEntry());
+ auto enumTypeEntry = fte->originator();
+ auto enumName = enumTypeEntry->targetLangName();
+ if (createRef)
+ enumName.prepend(enumTypeEntry->targetLangPackage() + u'.');
+ return "Combination of "_L1 + (createRef ? toRef(enumName) : enumName);
+ } else if (type.isEnum()) {
+ auto enumTypeEntry = std::static_pointer_cast<const EnumTypeEntry>(type.typeEntry());
+ auto enumName = enumTypeEntry->targetLangName();
+ if (createRef)
+ enumName.prepend(enumTypeEntry->targetLangPackage() + u'.');
+ return createRef ? toRef(enumName) : enumName;
+ }
+
+ if (type.isConstant() && name == "char"_L1 && type.indirections() == 1)
+ return "str"_L1;
+
+ if (type.isContainer()) {
QString strType = translateType(type, cppClass, Options(ExcludeConst) | ExcludeReference);
strType.remove(u'*');
strType.remove(u'>');
@@ -619,16 +805,19 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType &type,
strType = QString::fromLatin1("Dictionary with keys of type %1 and values of type %2.")
.arg(types[0], types[1]);
}
- } else {
- auto k = AbstractMetaClass::findClass(api().classes(), type.typeEntry());
- strType = k ? k->fullName() : type.name();
- strType = QStringLiteral(":any:`") + strType + u'`';
+ return strType;
}
- return strType;
+
+ if (auto k = AbstractMetaClass::findClass(api().classes(), type.typeEntry()))
+ return createRef ? toRef(k->fullName()) : k->name();
+
+ return createRef ? toRef(name) : name;
}
-QString QtDocGenerator::getFuncName(const AbstractMetaFunctionCPtr& cppFunc)
+QString QtDocGenerator::getFuncName(const AbstractMetaFunctionCPtr &cppFunc)
{
+ if (cppFunc->isConstructor())
+ return "__init__"_L1;
QString result = cppFunc->name();
if (cppFunc->isOperatorOverload()) {
const QString pythonOperator = Generator::pythonOperatorFunctionName(result);
@@ -639,14 +828,16 @@ QString QtDocGenerator::getFuncName(const AbstractMetaFunctionCPtr& cppFunc)
return result;
}
-void QtDocGenerator::writeParameterType(TextStream& s, const AbstractMetaClass* cppClass,
+void QtDocGenerator::writeParameterType(TextStream &s,
+ const AbstractMetaClassCPtr &cppClass,
const AbstractMetaArgument &arg) const
{
s << ":param " << arg.name() << ": "
<< translateToPythonType(arg.type(), cppClass) << '\n';
}
-void QtDocGenerator::writeFunctionParametersType(TextStream &s, const AbstractMetaClass *cppClass,
+void QtDocGenerator::writeFunctionParametersType(TextStream &s,
+ const AbstractMetaClassCPtr &cppClass,
const AbstractMetaFunctionCPtr &func) const
{
s << '\n';
@@ -656,35 +847,57 @@ void QtDocGenerator::writeFunctionParametersType(TextStream &s, const AbstractMe
writeParameterType(s, cppClass, arg);
}
- if (!func->isConstructor() && !func->isVoid()) {
-
- QString retType;
+ QString retType;
+ if (!func->isConstructor()) {
// check if the return type was modified
- for (const auto &mod : func->modifications()) {
- for (const ArgumentModification &argMod : mod.argument_mods()) {
- if (argMod.index() == 0) {
- retType = argMod.modifiedType();
- break;
- }
- }
- }
-
- if (retType.isEmpty())
+ retType = func->modifiedTypeName();
+ if (retType.isEmpty() && !func->isVoid())
retType = translateToPythonType(func->type(), cppClass);
- s << ":rtype: " << retType << '\n';
}
+
+ if (!retType.isEmpty())
+ s << ":rtype: " << retType << '\n';
+
s << '\n';
}
-void QtDocGenerator::writeFunction(TextStream& s, const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func, bool indexed)
+static bool containsFunctionDirective(const DocModification &dm)
{
- s << functionSignature(cppClass, func);
+ return dm.mode() != TypeSystem::DocModificationXPathReplace
+ && dm.code().contains(".. py:"_L1);
+}
- {
+void QtDocGenerator::writeFunctions(TextStream &s, const AbstractMetaFunctionCList &funcs,
+ const AbstractMetaClassCPtr &cppClass, const QString &scope)
+{
+ QString lastName;
+ for (const auto &func : funcs) {
+ const bool indexed = func->name() != lastName;
+ lastName = func->name();
+ writeFunction(s, func, cppClass, scope, indexed);
+ }
+}
+
+void QtDocGenerator::writeFunction(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass,
+ const QString &scope, bool indexed)
+{
+ const auto modifications = DocParser::getDocModifications(func, cppClass);
+
+ // Enable injecting parameter documentation by adding a complete function directive.
+ if (std::none_of(modifications.cbegin(), modifications.cend(), containsFunctionDirective)) {
+ if (func->ownerClass() == nullptr)
+ s << ".. py:function:: ";
+ else
+ s << (func->isStatic() ? ".. py:staticmethod:: " : ".. py:method:: ");
+ s << getFuncName(func) << formatArgs(func);
Indentation indentation(s);
if (!indexed)
s << "\n:noindex:";
+ if (func->cppAttributes().testFlag(FunctionAttribute::Final))
+ s << "\n:final:";
+ else if (func->isAbstract())
+ s << "\n:abstractmethod:";
s << "\n\n";
writeFunctionParametersType(s, cppClass, func);
const auto version = versionOf(func->typeEntry());
@@ -693,31 +906,94 @@ void QtDocGenerator::writeFunction(TextStream& s, const AbstractMetaClass* cppCl
if (func->isDeprecated())
s << rstDeprecationNote("function");
}
- writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func);
- if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) {
- writeFormattedBriefText(s, func->documentation(), cppClass);
- writeFormattedDetailedText(s, func->documentation(), cppClass);
+
+ writeFunctionDocumentation(s, func, modifications, scope);
+
+ if (auto propIndex = func->propertySpecIndex(); propIndex >= 0) {
+ const QString name = cppClass->propertySpecs().at(propIndex).name();
+ const QString target = propertyRefTarget(name);
+ if (func->isPropertyReader())
+ s << "\nGetter of property " << propRef(target) << " .\n\n";
+ else if (func->isPropertyWriter())
+ s << "\nSetter of property " << propRef(target) << " .\n\n";
+ else if (func->isPropertyResetter())
+ s << "\nReset function of property " << propRef(target) << " .\n\n";
+ else if (func->attributes().testFlag(AbstractMetaFunction::Attribute::PropertyNotify))
+ s << "\nNotification signal of property " << propRef(target) << " .\n\n";
+ }
+}
+
+void QtDocGenerator::writeFunctionDocumentation(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ const DocModificationList &modifications,
+ const QString &scope) const
+
+{
+ writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, modifications, func, scope);
+ if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, modifications, func, scope)) {
+ writeFormattedBriefText(s, func->documentation(), scope);
+ writeFormattedDetailedText(s, func->documentation(), scope);
}
- writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func);
+ writeInjectDocumentation(s, TypeSystem::DocModificationAppend, modifications, func, scope);
+}
+
+static QStringList fileListToToc(const QStringList &items)
+{
+ QStringList result;
+ result.reserve(items.size());
+ std::transform(items.cbegin(), items.cend(), std::back_inserter(result),
+ fileNameToTocEntry);
+ return result;
+}
+
+static QStringList functionListToToc(const AbstractMetaFunctionCList &functions)
+{
+ QStringList result;
+ result.reserve(functions.size());
+ for (const auto &f : functions)
+ result.append(f->name());
+ // Functions are sorted by the Metabuilder; erase overloads
+ result.erase(std::unique(result.begin(), result.end()), result.end());
+ return result;
}
-static void writeFancyToc(TextStream& s, const QStringList& items)
+static QStringList enumListToToc(const AbstractMetaEnumList &enums)
+{
+ QStringList result;
+ result.reserve(enums.size());
+ for (const auto &e : enums)
+ result.append(e.name());
+ return result;
+}
+
+// Sort entries for a TOC by first character, dropping the
+// leading common Qt prefixes like 'Q'.
+static QChar sortKey(const QString &key)
+{
+ const auto size = key.size();
+ if (size >= 2 && (key.at(0) == u'Q' || key.at(0) == u'q') && key.at(1).isUpper())
+ return key.at(1); // "QClass" -> 'C', "qSin()" -> 'S'
+ if (size >= 3 && key.startsWith("Q_"_L1))
+ return key.at(2).toUpper(); // "Q_ARG" -> 'A'
+ if (size >= 4 && key.startsWith("QT_"_L1))
+ return key.at(3).toUpper(); // "QT_TR" -> 'T'
+ auto idx = 0;
+ for (; idx < size && key.at(idx) == u'_'; ++idx) {
+ } // "__init__" -> 'I'
+ return idx < size ? key.at(idx).toUpper() : u'A';
+}
+
+static void writeFancyToc(TextStream& s, QAnyStringView title,
+ const QStringList& items,
+ QLatin1StringView referenceType)
{
using TocMap = QMap<QChar, QStringList>;
+
+ if (items.isEmpty())
+ return;
+
TocMap tocMap;
- QChar idx;
- for (QString item : items) {
- if (item.isEmpty())
- continue;
- item.chop(4); // Remove the .rst extension
- // skip namespace if necessary
- const QString className = item.split(u'.').last();
- if (className.startsWith(u'Q') && className.length() > 1)
- idx = className[1];
- else
- idx = className[0];
- tocMap[idx] << item;
- }
+ for (const QString &item : items)
+ tocMap[sortKey(item)] << item;
static const qsizetype numColumns = 4;
@@ -726,13 +1002,13 @@ static void writeFancyToc(TextStream& s, const QStringList& items)
QtXmlToSphinx::TableRow row;
const QString charEntry = u"**"_s + it.key() + u"**"_s;
row << QtXmlToSphinx::TableCell(charEntry);
- for (const QString &item : qAsConst(it.value())) {
+ for (const QString &item : std::as_const(it.value())) {
if (row.size() >= numColumns) {
table.appendRow(row);
row.clear();
row << QtXmlToSphinx::TableCell(QString{});
}
- const QString entry = u"* :doc:`"_s + item + u'`';
+ const QString entry = "* :"_L1 + referenceType + ":`"_L1 + item + u'`';
row << QtXmlToSphinx::TableCell(entry);
}
if (row.size() > 1)
@@ -740,24 +1016,70 @@ static void writeFancyToc(TextStream& s, const QStringList& items)
}
table.normalize();
- s << ".. container:: pysidetoc\n\n";
+ s << '\n' << headline(title) << ".. container:: pysidetoc\n\n";
table.format(s);
}
bool QtDocGenerator::finishGeneration()
{
- if (!api().classes().isEmpty())
+ for (const auto &f : api().globalFunctions()) {
+ auto ncf = std::const_pointer_cast<AbstractMetaFunction>(f);
+ m_docParser->fillGlobalFunctionDocumentation(ncf);
+ m_packages[f->targetLangPackage()].globalFunctions.append(f);
+ }
+
+ for (auto e : api().globalEnums()) {
+ m_docParser->fillGlobalEnumDocumentation(e);
+ m_packages[e.typeEntry()->targetLangPackage()].globalEnums.append(e);
+ }
+
+ if (!m_packages.isEmpty())
writeModuleDocumentation();
- if (!m_additionalDocumentationList.isEmpty())
+ if (!m_options.additionalDocumentationList.isEmpty())
writeAdditionalDocumentation();
+ if (!m_options.inheritanceFile.isEmpty() && !writeInheritanceFile())
+ return false;
return true;
}
+bool QtDocGenerator::writeInheritanceFile()
+{
+ QFile inheritanceFile(m_options.inheritanceFile);
+ if (!inheritanceFile.open(QIODevice::WriteOnly | QIODevice::Text))
+ throw Exception(msgCannotOpenForWriting(m_options.inheritanceFile));
+
+ QJsonObject dict;
+ for (const auto &c : api().classes()) {
+ const auto &bases = c->baseClasses();
+ if (!bases.isEmpty()) {
+ QJsonArray list;
+ for (const auto &base : bases)
+ list.append(QJsonValue(base->fullName()));
+ dict[c->fullName()] = list;
+ }
+ }
+ QJsonDocument document;
+ document.setObject(dict);
+ inheritanceFile.write(document.toJson(QJsonDocument::Compact));
+ return true;
+}
+
+// Remove function entries that have extra documentation pages
+static inline void removeExtraDocs(const QStringList &extraTocEntries,
+ AbstractMetaFunctionCList *functions)
+{
+ auto predicate = [&extraTocEntries](const AbstractMetaFunctionCPtr &f) {
+ return extraTocEntries.contains(f->name());
+ };
+ functions->erase(std::remove_if(functions->begin(),functions->end(), predicate),
+ functions->end());
+}
+
void QtDocGenerator::writeModuleDocumentation()
{
- QMap<QString, QStringList>::iterator it = m_packages.begin();
- for (; it != m_packages.end(); ++it) {
- std::sort(it.value().begin(), it.value().end());
+ for (auto it = m_packages.begin(), end = m_packages.end(); it != end; ++it) {
+ auto &docPackage = it.value();
+ std::sort(docPackage.classPages.begin(), docPackage.classPages.end());
QString key = it.key();
key.replace(u'.', u'/');
@@ -766,9 +1088,7 @@ void QtDocGenerator::writeModuleDocumentation()
TextStream& s = output.stream;
const QString &title = it.key();
- s << ".. module:: " << title << "\n\n"
- << title << '\n'
- << Pad('*', title.length()) << "\n\n";
+ s << ".. module:: " << title << "\n\n" << headline(title, '*');
// Store the it.key() in a QString so that it can be stripped off unwanted
// information when neeeded. For example, the RST files in the extras directory
@@ -779,11 +1099,12 @@ void QtDocGenerator::writeModuleDocumentation()
moduleName.remove(0, lastIndex + 1);
// Search for extra-sections
- if (!m_extraSectionDir.isEmpty()) {
- QDir extraSectionDir(m_extraSectionDir);
+ QStringList extraTocEntries;
+ if (!m_options.extraSectionDir.isEmpty()) {
+ QDir extraSectionDir(m_options.extraSectionDir);
if (!extraSectionDir.exists()) {
- const QString m = QStringLiteral("Extra sections directory ") +
- m_extraSectionDir + QStringLiteral(" doesn't exist");
+ const QString m = u"Extra sections directory "_s +
+ m_options.extraSectionDir + u" doesn't exist"_s;
throw Exception(m);
}
@@ -791,31 +1112,26 @@ void QtDocGenerator::writeModuleDocumentation()
const QString filter = moduleName + u".?*.rst"_s;
const auto fileList =
extraSectionDir.entryInfoList({filter}, QDir::Files, QDir::Name);
- for (const auto &fi : fileList) {
- // Strip to "Property.rst" in output directory
- const QString newFileName = fi.fileName().mid(moduleName.size() + 1);
- it.value().append(newFileName);
- const QString newFilePath = outputDir + u'/' + newFileName;
- if (QFile::exists(newFilePath))
- QFile::remove(newFilePath);
- if (!QFile::copy(fi.absoluteFilePath(), newFilePath)) {
- qCDebug(lcShibokenDoc).noquote().nospace() << "Error copying extra doc "
- << QDir::toNativeSeparators(fi.absoluteFilePath())
- << " to " << QDir::toNativeSeparators(newFilePath);
- }
- }
+ for (const auto &fi : fileList)
+ readExtraDoc(fi, moduleName, outputDir, &docPackage, &extraTocEntries);
}
+ removeExtraDocs(extraTocEntries, &docPackage.globalFunctions);
+ const bool hasGlobals = !docPackage.globalFunctions.isEmpty()
+ || !docPackage.globalEnums.isEmpty();
+ const QString globalsPage = moduleName + "_globals.rst"_L1;
+
s << ".. container:: hide\n\n" << indent
<< ".. toctree::\n" << indent
<< ":maxdepth: 1\n\n";
- for (const QString &className : qAsConst(it.value()))
+ if (hasGlobals)
+ s << globalsPage << '\n';
+ for (const QString &className : std::as_const(docPackage.classPages))
s << className << '\n';
- s << "\n\n" << outdent << outdent
- << "Detailed Description\n--------------------\n\n";
+ s << "\n\n" << outdent << outdent << headline("Detailed Description");
// module doc is always wrong and C++istic, so go straight to the extra directory!
- QFile moduleDoc(m_extraSectionDir + u'/' + moduleName
+ QFile moduleDoc(m_options.extraSectionDir + u'/' + moduleName
+ u".rst"_s);
if (moduleDoc.open(QIODevice::ReadOnly | QIODevice::Text)) {
s << moduleDoc.readAll();
@@ -826,19 +1142,48 @@ void QtDocGenerator::writeModuleDocumentation()
if (moduleDoc.format() == Documentation::Native) {
QString context = it.key();
QtXmlToSphinx::stripPythonQualifiers(&context);
- QtXmlToSphinx x(this, m_parameters, moduleDoc.detailed(), context);
+ QtXmlToSphinx x(this, m_options.parameters, moduleDoc.detailed(), context);
s << x;
} else {
s << moduleDoc.detailed();
}
}
- s << "\nList of Classes\n"
- << "---------------\n\n";
- writeFancyToc(s, it.value());
+ writeFancyToc(s, "List of Classes", fileListToToc(docPackage.classPages),
+ "class"_L1);
+ writeFancyToc(s, "List of Decorators", fileListToToc(docPackage.decoratorPages),
+ "deco"_L1);
+ writeFancyToc(s, "List of Functions", functionListToToc(docPackage.globalFunctions),
+ "py:func"_L1);
+ writeFancyToc(s, "List of Enumerations", enumListToToc(docPackage.globalEnums),
+ "any"_L1);
output.done();
+
+ if (hasGlobals)
+ writeGlobals(it.key(), outputDir + u'/' + globalsPage, docPackage);
+ }
+}
+
+void QtDocGenerator::writeGlobals(const QString &package,
+ const QString &fileName,
+ const DocPackage &docPackage)
+{
+ FileOut output(fileName);
+ TextStream &s = output.stream;
+
+ // Write out functions with injected documentation
+ if (!docPackage.globalFunctions.isEmpty()) {
+ s << currentModule(package) << headline("Functions");
+ writeFunctions(s, docPackage.globalFunctions, {}, {});
+ }
+
+ if (!docPackage.globalEnums.isEmpty()) {
+ s << headline("Enumerations");
+ writeEnums(s, docPackage.globalEnums, package);
}
+
+ output.done();
}
static inline QString msgNonExistentAdditionalDocFile(const QString &dir,
@@ -853,7 +1198,7 @@ static inline QString msgNonExistentAdditionalDocFile(const QString &dir,
void QtDocGenerator::writeAdditionalDocumentation() const
{
- QFile additionalDocumentationFile(m_additionalDocumentationList);
+ QFile additionalDocumentationFile(m_options.additionalDocumentationList);
if (!additionalDocumentationFile.open(QIODevice::ReadOnly | QIODevice::Text))
throw Exception(msgCannotOpenForReading(additionalDocumentationFile));
@@ -878,8 +1223,8 @@ void QtDocGenerator::writeAdditionalDocumentation() const
targetDir = outDir.absolutePath();
} else {
if (!outDir.exists(dir) && !outDir.mkdir(dir)) {
- const QString m = QStringLiteral("Cannot create directory ")
- + dir + QStringLiteral(" under ")
+ const QString m = "Cannot create directory "_L1
+ + dir + " under "_L1
+ QDir::toNativeSeparators(outputDirectory());
throw Exception(m);
}
@@ -887,7 +1232,7 @@ void QtDocGenerator::writeAdditionalDocumentation() const
}
} else {
// Normal file entry
- QFileInfo fi(m_parameters.docDataDir + u'/' + line);
+ QFileInfo fi(m_options.parameters.docDataDir + u'/' + line);
if (fi.isFile()) {
const QString rstFileName = fi.baseName() + rstSuffix;
const QString rstFile = targetDir + u'/' + rstFileName;
@@ -905,7 +1250,7 @@ void QtDocGenerator::writeAdditionalDocumentation() const
// FIXME: This should be an exception, in principle, but it
// requires building all modules.
qCWarning(lcShibokenDoc, "%s",
- qPrintable(msgNonExistentAdditionalDocFile(m_parameters.docDataDir, line)));
+ qPrintable(msgNonExistentAdditionalDocFile(m_options.parameters.docDataDir, line)));
}
++count;
}
@@ -924,32 +1269,34 @@ void QtDocGenerator::writeAdditionalDocumentation() const
bool QtDocGenerator::doSetup()
{
- if (m_parameters.codeSnippetDirs.isEmpty()) {
- m_parameters.codeSnippetDirs =
- m_parameters.libSourceDir.split(QLatin1Char(PATH_SEP));
+ if (m_options.parameters.codeSnippetDirs.isEmpty()) {
+ m_options.parameters.codeSnippetDirs =
+ m_options.parameters.libSourceDir.split(QLatin1Char(PATH_SEP));
}
- if (m_docParser.isNull())
- m_docParser.reset(new QtDocParser);
+ if (m_docParser.isNull()) {
+ if (m_options.doxygen)
+ m_docParser.reset(new DoxygenParser);
+ else
+ m_docParser.reset(new QtDocParser);
+ }
- if (m_parameters.libSourceDir.isEmpty()
- || m_parameters.docDataDir.isEmpty()) {
+ if (m_options.parameters.libSourceDir.isEmpty()
+ || m_options.parameters.docDataDir.isEmpty()) {
qCWarning(lcShibokenDoc) << "Documentation data dir and/or Qt source dir not informed, "
"documentation will not be extracted from Qt sources.";
return false;
}
- m_docParser->setDocumentationDataDirectory(m_parameters.docDataDir);
- m_docParser->setLibrarySourceDirectory(m_parameters.libSourceDir);
- m_parameters.outputDirectory = outputDirectory();
+ m_docParser->setDocumentationDataDirectory(m_options.parameters.docDataDir);
+ m_docParser->setLibrarySourceDirectory(m_options.parameters.libSourceDir);
+ m_options.parameters.outputDirectory = outputDirectory();
return true;
}
-
-Generator::OptionDescriptions QtDocGenerator::options() const
+QList<OptionDescription> QtDocGenerator::options()
{
- auto result = Generator::options();
- result.append({
+ return {
{u"doc-parser=<parser>"_s,
u"The documentation parser used to interpret the documentation\n"
"input files (qdoc|doxygen)"_s},
@@ -963,27 +1310,52 @@ Generator::OptionDescriptions QtDocGenerator::options() const
u"Directory used to search for extra documentation sections"_s},
{u"library-source-dir=<dir>"_s,
u"Directory where library source code is located"_s},
- {additionalDocumentationOption() + u"=<file>"_s,
+ {additionalDocumentationOption + u"=<file>"_s,
u"List of additional XML files to be converted to .rst files\n"
- "(for example, tutorials)."_s}
- });
- return result;
+ "(for example, tutorials)."_s},
+ {u"inheritance-file=<file>"_s,
+ u"Generate a JSON file containing the class inheritance."_s},
+ {u"disable-inheritance-diagram"_s,
+ u"Disable the generation of the inheritance diagram."_s}
+ };
}
-bool QtDocGenerator::handleOption(const QString &key, const QString &value)
+class QtDocGeneratorOptionsParser : public OptionsParser
{
- if (Generator::handleOption(key, value))
+public:
+ explicit QtDocGeneratorOptionsParser(DocGeneratorOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString &key, OptionSource source) override;
+ bool handleOption(const QString &key, const QString &value, OptionSource source) override;
+
+private:
+ DocGeneratorOptions *m_options;
+};
+
+bool QtDocGeneratorOptionsParser::handleBoolOption(const QString &key, OptionSource)
+{
+ if (key == "disable-inheritance-diagram"_L1) {
+ m_options->inheritanceDiagram = false;
return true;
+ }
+ return false;
+}
+
+bool QtDocGeneratorOptionsParser::handleOption(const QString &key, const QString &value,
+ OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
if (key == u"library-source-dir") {
- m_parameters.libSourceDir = value;
+ m_options->parameters.libSourceDir = value;
return true;
}
if (key == u"documentation-data-dir") {
- m_parameters.docDataDir = value;
+ m_options->parameters.docDataDir = value;
return true;
}
if (key == u"documentation-code-snippets-dir") {
- m_parameters.codeSnippetDirs = value.split(QLatin1Char(PATH_SEP));
+ m_options->parameters.codeSnippetDirs = value.split(QLatin1Char(PATH_SEP));
return true;
}
@@ -991,28 +1363,39 @@ bool QtDocGenerator::handleOption(const QString &key, const QString &value)
const auto pos = value.indexOf(u':');
if (pos == -1)
return false;
- m_parameters.codeSnippetRewriteOld= value.left(pos);
- m_parameters.codeSnippetRewriteNew = value.mid(pos + 1);
+ m_options->parameters.codeSnippetRewriteOld= value.left(pos);
+ m_options->parameters.codeSnippetRewriteNew = value.mid(pos + 1);
return true;
}
if (key == u"documentation-extra-sections-dir") {
- m_extraSectionDir = value;
+ m_options->extraSectionDir = value;
return true;
}
if (key == u"doc-parser") {
qCDebug(lcShibokenDoc).noquote().nospace() << "doc-parser: " << value;
if (value == u"doxygen")
- m_docParser.reset(new DoxygenParser);
+ m_options->doxygen = true;
return true;
}
- if (key == additionalDocumentationOption()) {
- m_additionalDocumentationList = value;
+ if (key == additionalDocumentationOption) {
+ m_options->additionalDocumentationList = value;
return true;
}
+
+ if (key == u"inheritance-file") {
+ m_options->inheritanceFile = value;
+ return true;
+ }
+
return false;
}
+std::shared_ptr<OptionsParser> QtDocGenerator::createOptionsParser()
+{
+ return std::make_shared<QtDocGeneratorOptionsParser>(&m_options);
+}
+
bool QtDocGenerator::convertToRst(const QString &sourceFileName,
const QString &targetFileName,
const QString &context,
@@ -1028,20 +1411,65 @@ bool QtDocGenerator::convertToRst(const QString &sourceFileName,
sourceFile.close();
FileOut targetFile(targetFileName);
- QtXmlToSphinx x(this, m_parameters, doc, context);
+ QtXmlToSphinx x(this, m_options.parameters, doc, context);
targetFile.stream << x;
targetFile.done();
return true;
}
+GeneratorDocumentation
+ QtDocGenerator::generatorDocumentation(const AbstractMetaClassCPtr &cppClass)
+{
+ GeneratorDocumentation result;
+ const auto allFunctions = cppClass->functions();
+ result.allFunctions.reserve(allFunctions.size());
+ std::remove_copy_if(allFunctions.cbegin(), allFunctions.cend(),
+ std::back_inserter(result.allFunctions), shouldSkip);
+
+ std::stable_sort(result.allFunctions.begin(), result.allFunctions.end(), functionSort);
+
+ for (const auto &func : std::as_const(result.allFunctions)) {
+ if (func->isStatic())
+ result.tocStaticFunctions.append(func);
+ else if (func->isVirtual())
+ result.tocVirtuals.append(func);
+ else if (func->isSignal())
+ result.tocSignalFunctions.append(func);
+ else if (func->isSlot())
+ result.tocSlotFunctions.append(func);
+ else
+ result.tocNormalFunctions.append(func);
+ }
+
+ // Find the property getters/setters
+ for (const auto &spec: cppClass->propertySpecs()) {
+ GeneratorDocumentation::Property property;
+ property.name = spec.name();
+ property.type = spec.type();
+ property.documentation = spec.documentation();
+ if (!spec.read().isEmpty())
+ property.getter = AbstractMetaFunction::find(result.allFunctions, spec.read());
+ if (!spec.write().isEmpty())
+ property.setter = AbstractMetaFunction::find(result.allFunctions, spec.write());
+ if (!spec.reset().isEmpty())
+ property.reset = AbstractMetaFunction::find(result.allFunctions, spec.reset());
+ if (!spec.notify().isEmpty())
+ property.notify = AbstractMetaFunction::find(result.tocSignalFunctions, spec.notify());
+ result.properties.append(property);
+ }
+ std::sort(result.properties.begin(), result.properties.end());
+
+ return result;
+}
+
// QtXmlToSphinxDocGeneratorInterface
QString QtDocGenerator::expandFunction(const QString &function) const
{
- const int firstDot = function.indexOf(u'.');
- const AbstractMetaClass *metaClass = nullptr;
+ const auto firstDot = function.indexOf(u'.');
+ AbstractMetaClassCPtr metaClass;
if (firstDot != -1) {
const auto className = QStringView{function}.left(firstDot);
- for (auto cls : api().classes()) {
+ for (const auto &cls : api().classes()) {
if (cls->name() == className) {
metaClass = cls;
break;
@@ -1076,8 +1504,8 @@ QString QtDocGenerator::resolveContextForMethod(const QString &context,
{
const auto currentClass = QStringView{context}.split(u'.').constLast();
- const AbstractMetaClass *metaClass = nullptr;
- for (auto cls : api().classes()) {
+ AbstractMetaClassCPtr metaClass;
+ for (const auto &cls : api().classes()) {
if (cls->name() == currentClass) {
metaClass = cls;
break;
@@ -1092,8 +1520,8 @@ QString QtDocGenerator::resolveContextForMethod(const QString &context,
funcList.append(func);
}
- const AbstractMetaClass *implementingClass = nullptr;
- for (const auto &func : qAsConst(funcList)) {
+ AbstractMetaClassCPtr implementingClass;
+ for (const auto &func : std::as_const(funcList)) {
implementingClass = func->implementingClass();
if (implementingClass->name() == currentClass)
break;
@@ -1123,7 +1551,7 @@ QtXmlToSphinxLink QtDocGenerator::resolveLink(const QtXmlToSphinxLink &link) con
{
if (link.type != QtXmlToSphinxLink::Reference || !isRelativeHtmlFile(link.linkRef))
return link;
- static const QString prefix = QStringLiteral("https://doc.qt.io/qt-")
+ static const QString prefix = "https://doc.qt.io/qt-"_L1
+ QString::number(QT_VERSION_MAJOR) + u'/';
QtXmlToSphinxLink resolved = link;
resolved.type = QtXmlToSphinxLink::External;
@@ -1134,6 +1562,5 @@ QtXmlToSphinxLink QtDocGenerator::resolveLink(const QtXmlToSphinxLink &link) con
if (anchor != -1)
resolved.linkText.truncate(anchor);
}
- qDebug() << __FUNCTION__ << link << "->" << resolved;
return resolved;
}
diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
index b0f728fc4..3b1c82e74 100644
--- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
+++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
@@ -9,11 +9,15 @@
#include "generator.h"
#include "documentation.h"
+#include <optionsparser.h>
#include "typesystem_enums.h"
-#include "typesystem_typedefs.h"
+#include "modifications_typedefs.h"
#include "qtxmltosphinxinterface.h"
class DocParser;
+struct DocGeneratorOptions;
+struct GeneratorDocumentation;
+struct DocPackage;
/**
* The DocGenerator generates documentation from library being binded.
@@ -21,6 +25,8 @@ class DocParser;
class QtDocGenerator : public Generator, public QtXmlToSphinxDocGeneratorInterface
{
public:
+ Q_DISABLE_COPY_MOVE(QtDocGenerator)
+
QtDocGenerator();
~QtDocGenerator();
@@ -31,8 +37,8 @@ public:
return "QtDocGenerator";
}
- OptionDescriptions options() const override;
- bool handleOption(const QString &key, const QString &value) override;
+ static QList<OptionDescription> options();
+ static std::shared_ptr<OptionsParser> createOptionsParser();
// QtXmlToSphinxDocGeneratorInterface
QString expandFunction(const QString &function) const override;
@@ -43,64 +49,81 @@ public:
const QLoggingCategory &loggingCategory() const override;
QtXmlToSphinxLink resolveLink(const QtXmlToSphinxLink &) const override;
+ static QString getFuncName(const AbstractMetaFunctionCPtr &cppFunc);
+ static QString formatArgs(const AbstractMetaFunctionCPtr &func);
+
protected:
- bool shouldGenerate(const TypeEntry *) const override;
+ bool shouldGenerate(const TypeEntryCPtr &) const override;
static QString fileNameSuffix();
QString fileNameForContext(const GeneratorContext &context) const override;
void generateClass(TextStream &ts, const GeneratorContext &classContext) override;
bool finishGeneration() override;
private:
- void writeEnums(TextStream& s, const AbstractMetaClass* cppClass) const;
-
- void writeFields(TextStream &s, const AbstractMetaClass *cppClass) const;
- static QString functionSignature(const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func);
- void writeFunction(TextStream& s, const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func, bool indexed = true);
- void writeFunctionParametersType(TextStream &s, const AbstractMetaClass *cppClass,
+ void writeEnums(TextStream &s, const AbstractMetaEnumList &enums,
+ const QString &scope) const;
+
+ void writeFields(TextStream &s, const AbstractMetaClassCPtr &cppClass) const;
+ void writeFunctions(TextStream &s, const AbstractMetaFunctionCList &funcs,
+ const AbstractMetaClassCPtr &cppClass, const QString &scope);
+ void writeFunction(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaClassCPtr &cppClass = {},
+ const QString &scope = {}, bool indexed = true);
+ void writeFunctionDocumentation(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ const DocModificationList &modifications,
+ const QString &scope) const;
+ void writeFunctionParametersType(TextStream &s, const AbstractMetaClassCPtr &cppClass,
const AbstractMetaFunctionCPtr &func) const;
- static void writeFunctionList(TextStream& s, const AbstractMetaClass* cppClass);
- static void writeFunctionBlock(TextStream& s, const QString& title,
- QStringList& functions);
- void writeParameterType(TextStream &s, const AbstractMetaClass *cppClass,
+ static void writeFunctionToc(TextStream &s, const QString &title,
+ const AbstractMetaFunctionCList &functions);
+ static void writePropertyToc(TextStream &s,
+ const GeneratorDocumentation &doc);
+ void writeProperties(TextStream &s,
+ const GeneratorDocumentation &doc,
+ const AbstractMetaClassCPtr &cppClass) const;
+ void writeParameterType(TextStream &s, const AbstractMetaClassCPtr &cppClass,
const AbstractMetaArgument &arg) const;
-
- void writeConstructors(TextStream &s, const AbstractMetaClass *cppClass) const;
-
void writeFormattedText(TextStream &s, const QString &doc,
Documentation::Format format,
- const AbstractMetaClass *metaClass = nullptr) const;
+ const QString &scope = {}) const;
void writeFormattedBriefText(TextStream &s, const Documentation &doc,
- const AbstractMetaClass *metaclass = nullptr) const;
+ const QString &scope = {}) const;
void writeFormattedDetailedText(TextStream &s, const Documentation &doc,
- const AbstractMetaClass *metaclass = nullptr) const;
-
- bool writeInjectDocumentation(TextStream& s, TypeSystem::DocModificationMode mode,
- const AbstractMetaClass* cppClass,
- const AbstractMetaFunctionCPtr &func);
+ const QString &scope = {}) const;
+
+ bool writeInjectDocumentation(TextStream &s, TypeSystem::DocModificationMode mode,
+ const AbstractMetaClassCPtr &cppClass) const;
+ bool writeInjectDocumentation(TextStream &s, TypeSystem::DocModificationMode mode,
+ const DocModificationList &modifications,
+ const AbstractMetaFunctionCPtr &func,
+ const QString &scope = {}) const;
+ bool writeDocModifications(TextStream &s, const DocModificationList &mods,
+ TypeSystem::DocModificationMode mode,
+ const QString &scope = {}) const;
static void writeDocSnips(TextStream &s, const CodeSnipList &codeSnips,
TypeSystem::CodeSnipPosition position, TypeSystem::Language language);
void writeModuleDocumentation();
+ void writeGlobals(const QString &package, const QString &fileName,
+ const DocPackage &docPackage);
void writeAdditionalDocumentation() const;
+ bool writeInheritanceFile();
- static QString parseArgDocStyle(const AbstractMetaClass *cppClass,
- const AbstractMetaFunctionCPtr &func);
- QString translateToPythonType(const AbstractMetaType &type, const AbstractMetaClass *cppClass) const;
- static QString getFuncName(const AbstractMetaFunctionCPtr& cppFunc);
+ QString translateToPythonType(const AbstractMetaType &type,
+ const AbstractMetaClassCPtr &cppClass,
+ bool createRef = true) const;
bool convertToRst(const QString &sourceFileName,
const QString &targetFileName,
const QString &context = QString(),
QString *errorMessage = nullptr) const;
- QString m_extraSectionDir;
+ static GeneratorDocumentation generatorDocumentation(const AbstractMetaClassCPtr &cppClass);
+
QStringList m_functionList;
- QMap<QString, QStringList> m_packages;
+ QMap<QString, DocPackage> m_packages;
QScopedPointer<DocParser> m_docParser;
- QtXmlToSphinxParameters m_parameters;
- QString m_additionalDocumentationList;
+ static DocGeneratorOptions m_options;
};
#endif // DOCGENERATOR_H
diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
index c29d2596c..55c1d2090 100644
--- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
+++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
@@ -12,16 +12,13 @@
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
+#include <QtCore/QHash>
#include <QtCore/QLoggingCategory>
#include <QtCore/QRegularExpression>
#include <QtCore/QXmlStreamReader>
using namespace Qt::StringLiterals;
-static inline QString nameAttribute() { return QStringLiteral("name"); }
-static inline QString titleAttribute() { return QStringLiteral("title"); }
-static inline QString fullTitleAttribute() { return QStringLiteral("fulltitle"); }
-
QString msgTagWarning(const QXmlStreamReader &reader, const QString &context,
const QString &tag, const QString &message)
{
@@ -62,6 +59,20 @@ static bool isHttpLink(const QString &ref)
return ref.startsWith(u"http://") || ref.startsWith(u"https://");
}
+static QString trimRight(QString s)
+{
+ while (!s.isEmpty() && s.crbegin()->isSpace())
+ s.chop(1);
+ return s;
+}
+
+static QString trimLeadingNewlines(QString s)
+{
+ while (!s.isEmpty() && s.at(0) == u'\n')
+ s.remove(0, 1);
+ return s;
+}
+
QDebug operator<<(QDebug d, const QtXmlToSphinxLink &l)
{
static const QHash<QtXmlToSphinxLink::Type, const char *> typeName = {
@@ -406,32 +417,49 @@ void QtXmlToSphinx::callHandler(WebXmlTag t, QXmlStreamReader &r)
void QtXmlToSphinx::formatCurrentTable()
{
- if (m_currentTable.isEmpty())
+ Q_ASSERT(!m_tables.isEmpty());
+ auto &table = m_tables.back();
+ if (table.isEmpty())
return;
- m_currentTable.normalize();
+ table.normalize();
m_output << '\n';
- m_currentTable.format(m_output);
+ table.format(m_output);
}
void QtXmlToSphinx::pushOutputBuffer()
{
- m_buffers.append(StringSharedPtr(new QString{}));
- m_output.setString(m_buffers.top().data());
+ m_buffers.append(std::make_shared<QString>());
+ m_output.setString(m_buffers.top().get());
}
QString QtXmlToSphinx::popOutputBuffer()
{
Q_ASSERT(!m_buffers.isEmpty());
- QString result(*m_buffers.top().data());
+ QString result(*m_buffers.top());
m_buffers.pop();
- m_output.setString(m_buffers.isEmpty() ? nullptr : m_buffers.top().data());
+ m_output.setString(m_buffers.isEmpty() ? nullptr : m_buffers.top().get());
return result;
}
+constexpr auto autoTranslatedPlaceholder = "AUTO_GENERATED\n"_L1;
+constexpr auto autoTranslatedNote =
+R"(.. warning::
+ This section contains snippets that were automatically
+ translated from C++ to Python and may contain errors.
+
+)"_L1;
+
+void QtXmlToSphinx::setAutoTranslatedNote(QString *str) const
+{
+ if (m_containsAutoTranslations)
+ str->replace(autoTranslatedPlaceholder, autoTranslatedNote);
+ else
+ str->remove(autoTranslatedPlaceholder);
+}
+
QString QtXmlToSphinx::transform(const QString& doc)
{
Q_ASSERT(m_buffers.isEmpty());
- Indentation indentation(m_output);
if (doc.trimmed().isEmpty())
return doc;
@@ -439,6 +467,9 @@ QString QtXmlToSphinx::transform(const QString& doc)
QXmlStreamReader reader(doc);
+ m_output << autoTranslatedPlaceholder;
+ Indentation indentation(m_output);
+
while (!reader.atEnd()) {
QXmlStreamReader::TokenType token = reader.readNext();
if (reader.hasError()) {
@@ -470,7 +501,7 @@ QString QtXmlToSphinx::transform(const QString& doc)
if (!m_inlineImages.isEmpty()) {
// Write out inline image definitions stored in handleInlineImageTag().
m_output << '\n' << disableIndent;
- for (const InlineImage &img : qAsConst(m_inlineImages))
+ for (const InlineImage &img : std::as_const(m_inlineImages))
m_output << ".. |" << img.tag << "| image:: " << img.href << '\n';
m_output << '\n' << enableIndent;
m_inlineImages.clear();
@@ -479,6 +510,7 @@ QString QtXmlToSphinx::transform(const QString& doc)
m_output.flush();
QString retval = popOutputBuffer();
Q_ASSERT(m_buffers.isEmpty());
+ setAutoTranslatedNote(&retval);
return retval;
}
@@ -527,7 +559,7 @@ static QString pySnippetName(const QString &path, SnippetType type)
QtXmlToSphinx::Snippet QtXmlToSphinx::readSnippetFromLocations(const QString &path,
const QString &identifier,
const QString &fallbackPath,
- QString *errorMessage) const
+ QString *errorMessage)
{
// For anything else but C++ header/sources (no conversion to Python),
// use existing fallback paths first.
@@ -549,6 +581,7 @@ QtXmlToSphinx::Snippet QtXmlToSphinx::readSnippetFromLocations(const QString &pa
rewrittenPath.replace(m_parameters.codeSnippetRewriteOld,
m_parameters.codeSnippetRewriteNew);
const QString code = readFromLocation(rewrittenPath, identifier, errorMessage);
+ m_containsAutoTranslations = true;
return {code, code.isNull() ? Snippet::Error : Snippet::Converted};
}
}
@@ -560,7 +593,7 @@ QtXmlToSphinx::Snippet QtXmlToSphinx::readSnippetFromLocations(const QString &pa
}
}
- resolvedPath =resolveFile(locations, path);
+ resolvedPath = resolveFile(locations, path);
if (!resolvedPath.isEmpty()) {
const QString code = readFromLocation(resolvedPath, identifier, errorMessage);
return {code, code.isNull() ? Snippet::Error : Snippet::Resolved};
@@ -576,6 +609,88 @@ QtXmlToSphinx::Snippet QtXmlToSphinx::readSnippetFromLocations(const QString &pa
return {{}, Snippet::Error};
}
+// Helpers for extracting qdoc snippets "#/// [id]"
+static QString fileNameOfDevice(const QIODevice *inputFile)
+{
+ const auto *file = qobject_cast<const QFile *>(inputFile);
+ return file ? QDir::toNativeSeparators(file->fileName()) : u"<stdin>"_s;
+}
+
+static QString msgSnippetNotFound(const QIODevice &inputFile,
+ const QString &identifier)
+{
+ return u"Code snippet file found ("_s + fileNameOfDevice(&inputFile)
+ + u"), but snippet ["_s + identifier + u"] not found."_s;
+}
+
+static QString msgEmptySnippet(const QIODevice &inputFile, int lineNo,
+ const QString &identifier)
+{
+ return u"Empty code snippet ["_s + identifier + u"] at "_s
+ + fileNameOfDevice(&inputFile) + u':' + QString::number(lineNo);
+}
+
+// Pattern to match qdoc snippet IDs with "#/// [id]" comments and helper to find ID
+static const QRegularExpression &snippetIdPattern()
+{
+ static const QRegularExpression result(uR"RX((//|#) *! *\[([^]]+)\])RX"_s);
+ Q_ASSERT(result.isValid());
+ return result;
+}
+
+static bool matchesSnippetId(QRegularExpressionMatchIterator it,
+ const QString &identifier)
+{
+ while (it.hasNext()) {
+ if (it.next().captured(2) == identifier)
+ return true;
+ }
+ return false;
+}
+
+QString QtXmlToSphinx::readSnippet(QIODevice &inputFile, const QString &identifier,
+ QString *errorMessage)
+{
+ const QByteArray identifierBA = identifier.toUtf8();
+ // Lambda that matches the snippet id
+ const auto snippetIdPred = [&identifierBA, &identifier](const QByteArray &lineBA)
+ {
+ const bool isComment = lineBA.contains('/') || lineBA.contains('#');
+ if (!isComment || !lineBA.contains(identifierBA))
+ return false;
+ const QString line = QString::fromUtf8(lineBA);
+ return matchesSnippetId(snippetIdPattern().globalMatch(line), identifier);
+ };
+
+ // Find beginning, skip over
+ int lineNo = 1;
+ for (; !inputFile.atEnd() && !snippetIdPred(inputFile.readLine());
+ ++lineNo) {
+ }
+
+ if (inputFile.atEnd()) {
+ *errorMessage = msgSnippetNotFound(inputFile, identifier);
+ return {};
+ }
+
+ QString code;
+ for (; !inputFile.atEnd(); ++lineNo) {
+ const QString line = QString::fromUtf8(inputFile.readLine());
+ auto it = snippetIdPattern().globalMatch(line);
+ if (it.hasNext()) { // Skip snippet id lines
+ if (matchesSnippetId(it, identifier))
+ break;
+ } else {
+ code += line;
+ }
+ }
+
+ if (code.isEmpty())
+ *errorMessage = msgEmptySnippet(inputFile, lineNo, identifier);
+
+ return code;
+}
+
QString QtXmlToSphinx::readFromLocation(const QString &location, const QString &identifier,
QString *errorMessage)
{
@@ -585,7 +700,7 @@ QString QtXmlToSphinx::readFromLocation(const QString &location, const QString &
QTextStream(errorMessage) << "Could not read code snippet file: "
<< QDir::toNativeSeparators(inputFile.fileName())
<< ": " << inputFile.errorString();
- return QString(); // null
+ return {}; // null
}
QString code = u""_s; // non-null
@@ -595,34 +710,8 @@ QString QtXmlToSphinx::readFromLocation(const QString &location, const QString &
return CodeSnipHelpers::fixSpaces(code);
}
- const QRegularExpression searchString(u"//!\\s*\\["_s
- + identifier + u"\\]"_s);
- Q_ASSERT(searchString.isValid());
- static const QRegularExpression codeSnippetCode(u"//!\\s*\\[[\\w\\d\\s]+\\]"_s);
- Q_ASSERT(codeSnippetCode.isValid());
-
- bool getCode = false;
-
- while (!inputFile.atEnd()) {
- QString line = QString::fromUtf8(inputFile.readLine());
- if (getCode && !line.contains(searchString)) {
- line.remove(codeSnippetCode);
- code += line;
- } else if (line.contains(searchString)) {
- if (getCode)
- break;
- getCode = true;
- }
- }
-
- if (!getCode) {
- QTextStream(errorMessage) << "Code snippet file found ("
- << QDir::toNativeSeparators(location) << "), but snippet ["
- << identifier << "] not found.";
- return QString(); // null
- }
-
- return CodeSnipHelpers::fixSpaces(code);
+ code = readSnippet(inputFile, identifier, errorMessage);
+ return code.isEmpty() ? QString{} : CodeSnipHelpers::fixSpaces(code); // maintain isNull()
}
void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader)
@@ -685,9 +774,9 @@ void QtXmlToSphinx::handleParaTagEnd()
{
QString result = popOutputBuffer().simplified();
if (result.startsWith(u"**Warning:**"))
- result.replace(0, 12, QStringLiteral(".. warning:: "));
+ result.replace(0, 12, ".. warning:: "_L1);
else if (result.startsWith(u"**Note:**"))
- result.replace(0, 9, QStringLiteral(".. note:: "));
+ result.replace(0, 9, ".. note:: "_L1);
m_output << result << "\n\n";
}
@@ -756,23 +845,23 @@ void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader)
}
}
-static inline QString functionLinkType() { return QStringLiteral("function"); }
-static inline QString classLinkType() { return QStringLiteral("class"); }
+constexpr auto functionLinkType = "function"_L1;
+constexpr auto classLinkType = "class"_L1;
static inline QString fixLinkType(QStringView type)
{
// TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties
// are recognized as such or not in the binding
if (type == u"property")
- return functionLinkType();
+ return functionLinkType;
if (type == u"typedef")
- return classLinkType();
+ return classLinkType;
return type.toString();
}
static inline QString linkSourceAttribute(const QString &type)
{
- if (type == functionLinkType() || type == classLinkType())
+ if (type == functionLinkType || type == classLinkType)
return u"raw"_s;
return type == u"enum" || type == u"page"
? type : u"href"_s;
@@ -798,7 +887,7 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader)
const QString text = textR.toString();
if (m_seeAlsoContext.isNull()) {
const QString type = text.endsWith(u"()")
- ? functionLinkType() : classLinkType();
+ ? functionLinkType : classLinkType;
m_seeAlsoContext.reset(handleLinkStart(type, text));
}
handleLinkText(m_seeAlsoContext.data(), text);
@@ -817,7 +906,7 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader)
}
}
-static inline QString fallbackPathAttribute() { return QStringLiteral("path"); }
+constexpr auto fallbackPathAttribute = "path"_L1;
template <class Indent> // const char*/class Indentor
void formatSnippet(TextStream &str, Indent indent, const QString &snippet)
@@ -852,14 +941,15 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader)
|| m_lastTagName == u"dots" || m_lastTagName == u"codeline";
if (consecutiveSnippet) {
m_output.flush();
- m_output.string()->chop(2);
+ m_output.string()->chop(1); // Strip newline from previous snippet
}
QString location = reader.attributes().value(u"location"_s).toString();
QString identifier = reader.attributes().value(u"identifier"_s).toString();
QString fallbackPath;
- if (reader.attributes().hasAttribute(fallbackPathAttribute()))
- fallbackPath = reader.attributes().value(fallbackPathAttribute()).toString();
+ if (reader.attributes().hasAttribute(fallbackPathAttribute))
+ fallbackPath = reader.attributes().value(fallbackPathAttribute).toString();
QString errorMessage;
+
const Snippet snippet = readSnippetFromLocations(location, identifier,
fallbackPath, &errorMessage);
if (!errorMessage.isEmpty())
@@ -882,6 +972,7 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader)
m_output << '\n';
}
}
+
void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader)
{
QXmlStreamReader::TokenType token = reader.tokenType();
@@ -912,11 +1003,11 @@ void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader)
if (token == QXmlStreamReader::StartElement) {
if (parentTag() == WebXmlTag::para)
handleParaTagEnd(); // End <para> to prevent the table from being rst-escaped
- m_currentTable.clear();
+ m_tables.push({});
} else if (token == QXmlStreamReader::EndElement) {
// write the table on m_output
formatCurrentTable();
- m_currentTable.clear();
+ m_tables.pop();
if (parentTag() == WebXmlTag::para)
handleParaTagStart();
}
@@ -932,7 +1023,7 @@ void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader)
} else if (token == QXmlStreamReader::EndElement) {
TableCell cell;
cell.data = popOutputBuffer().trimmed();
- m_currentTable.appendRow(TableRow(1, cell));
+ m_tables.back().appendRow(TableRow(1, cell));
}
}
@@ -941,18 +1032,20 @@ void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader)
{
QXmlStreamReader::TokenType token = reader.tokenType();
if (token == QXmlStreamReader::StartElement) {
- if (m_currentTable.isEmpty())
- m_currentTable.appendRow({});
- TableRow& row = m_currentTable.last();
+ auto &table = m_tables.back();
+ if (table.isEmpty())
+ table.appendRow({});
+ TableRow& row = table.last();
TableCell cell;
cell.colSpan = reader.attributes().value(u"colspan"_s).toShort();
cell.rowSpan = reader.attributes().value(u"rowspan"_s).toShort();
row << cell;
pushOutputBuffer();
} else if (token == QXmlStreamReader::EndElement) {
- QString data = popOutputBuffer().trimmed();
- if (!m_currentTable.isEmpty()) {
- TableRow& row = m_currentTable.last();
+ QString data = trimLeadingNewlines(trimRight(popOutputBuffer()));
+ auto &table = m_tables.back();
+ if (!table.isEmpty()) {
+ TableRow& row = table.last();
if (!row.isEmpty())
row.last().data = data;
}
@@ -965,15 +1058,16 @@ void QtXmlToSphinx::handleHeaderTag(QXmlStreamReader &reader)
// C++ header with "name"/"href" attributes.
if (reader.tokenType() == QXmlStreamReader::StartElement
&& !reader.attributes().hasAttribute(u"name"_s)) {
- m_currentTable.setHeaderEnabled(true);
- m_currentTable.appendRow({});
+ auto &table = m_tables.back();
+ table.setHeaderEnabled(true);
+ table.appendRow({});
}
}
void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader)
{
if (reader.tokenType() == QXmlStreamReader::StartElement)
- m_currentTable.appendRow({});
+ m_tables.back().appendRow({});
}
enum ListType { BulletList, OrderedList, EnumeratedList };
@@ -989,27 +1083,29 @@ static inline ListType webXmlListType(QStringView t)
void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader)
{
- // BUG We do not support a list inside a table cell
static ListType listType = BulletList;
QXmlStreamReader::TokenType token = reader.tokenType();
if (token == QXmlStreamReader::StartElement) {
+ m_tables.push({});
+ auto &table = m_tables.back();
listType = webXmlListType(reader.attributes().value(u"type"_s));
if (listType == EnumeratedList) {
- m_currentTable.appendRow(TableRow{TableCell(u"Constant"_s),
- TableCell(u"Description"_s)});
- m_currentTable.setHeaderEnabled(true);
+ table.appendRow(TableRow{TableCell(u"Constant"_s),
+ TableCell(u"Description"_s)});
+ table.setHeaderEnabled(true);
}
m_output.indent();
} else if (token == QXmlStreamReader::EndElement) {
m_output.outdent();
- if (!m_currentTable.isEmpty()) {
+ const auto &table = m_tables.back();
+ if (!table.isEmpty()) {
switch (listType) {
case BulletList:
case OrderedList: {
m_output << '\n';
const char *separator = listType == BulletList ? "* " : "#. ";
const char *indentLine = listType == BulletList ? " " : " ";
- for (const TableCell &cell : m_currentTable.constFirst()) {
+ for (const TableCell &cell : table.constFirst()) {
const auto itemLines = QStringView{cell.data}.split(u'\n');
m_output << separator << itemLines.constFirst() << '\n';
for (qsizetype i = 1, max = itemLines.size(); i < max; ++i)
@@ -1023,7 +1119,7 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader)
break;
}
}
- m_currentTable.clear();
+ m_tables.pop();
}
}
@@ -1065,7 +1161,7 @@ QtXmlToSphinxLink *QtXmlToSphinx::handleLinkStart(const QString &type, QString r
if (type == u"external" || isHttpLink(ref)) {
result->type = QtXmlToSphinxLink::External;
- } else if (type == functionLinkType() && !m_context.isEmpty()) {
+ } else if (type == functionLinkType && !m_context.isEmpty()) {
result->type = QtXmlToSphinxLink::Method;
const auto rawlinklist = QStringView{result->linkRef}.split(u'.');
if (rawlinklist.size() == 1 || rawlinklist.constFirst() == m_context) {
@@ -1076,9 +1172,9 @@ QtXmlToSphinxLink *QtXmlToSphinx::handleLinkStart(const QString &type, QString r
} else {
result->linkRef = m_generator->expandFunction(result->linkRef);
}
- } else if (type == functionLinkType() && m_context.isEmpty()) {
+ } else if (type == functionLinkType && m_context.isEmpty()) {
result->type = QtXmlToSphinxLink::Function;
- } else if (type == classLinkType()) {
+ } else if (type == classLinkType) {
result->type = QtXmlToSphinxLink::Class;
result->linkRef = m_generator->expandClass(m_context, result->linkRef);
} else if (type == u"enum") {
@@ -1118,10 +1214,10 @@ static QString fixLinkText(const QtXmlToSphinxLink *linkContext,
else
QtXmlToSphinx::stripPythonQualifiers(&linktext);
if (linkContext->linkRef == linktext)
- return QString();
+ return {};
if ((linkContext->type & QtXmlToSphinxLink::FunctionMask) != 0
&& (linkContext->linkRef + u"()"_s) == linktext) {
- return QString();
+ return {};
}
return linktext;
}
@@ -1149,7 +1245,7 @@ static bool copyImage(const QString &href, const QString &docDataDir,
const QLoggingCategory &lc, QString *errorMessage)
{
const QChar slash = u'/';
- const int lastSlash = href.lastIndexOf(slash);
+ const auto lastSlash = href.lastIndexOf(slash);
const QString imagePath = lastSlash != -1 ? href.left(lastSlash) : QString();
const QString imageFileName = lastSlash != -1 ? href.right(href.size() - lastSlash - 1) : href;
QFileInfo imageSource(docDataDir + slash + href);
@@ -1162,7 +1258,7 @@ static bool copyImage(const QString &href, const QString &docDataDir,
// FIXME: Not perfect yet, should have knowledge about namespaces (DataVis3D) or
// nested classes "Pyside2.QtGui.QTouchEvent.QTouchPoint".
QString relativeTargetDir = context;
- const int lastDot = relativeTargetDir.lastIndexOf(u'.');
+ const auto lastDot = relativeTargetDir.lastIndexOf(u'.');
if (lastDot != -1)
relativeTargetDir.truncate(lastDot);
relativeTargetDir.replace(u'.', slash);
@@ -1229,7 +1325,7 @@ void QtXmlToSphinx::handleInlineImageTag(QXmlStreamReader& reader)
// enclosed by '|' and define it further down. Determine tag from the base
//file name with number.
QString tag = href;
- int pos = tag.lastIndexOf(u'/');
+ auto pos = tag.lastIndexOf(u'/');
if (pos != -1)
tag.remove(0, pos + 1);
pos = tag.indexOf(u'.');
@@ -1297,11 +1393,11 @@ void QtXmlToSphinx::handlePageTag(QXmlStreamReader &reader)
m_output << disableIndent;
- const auto title = reader.attributes().value(titleAttribute());
+ const auto title = reader.attributes().value("title");
if (!title.isEmpty())
m_output << rstLabel(title.toString());
- const auto fullTitle = reader.attributes().value(fullTitleAttribute());
+ const auto fullTitle = reader.attributes().value("fulltitle");
const int size = fullTitle.isEmpty()
? writeEscapedRstText(m_output, title)
: writeEscapedRstText(m_output, fullTitle);
@@ -1314,7 +1410,7 @@ void QtXmlToSphinx::handleTargetTag(QXmlStreamReader &reader)
{
if (reader.tokenType() != QXmlStreamReader::StartElement)
return;
- const auto name = reader.attributes().value(nameAttribute());
+ const auto name = reader.attributes().value("name");
if (!name.isEmpty())
m_output << rstLabel(name.toString());
}
@@ -1405,7 +1501,7 @@ void QtXmlToSphinx::Table::normalize()
//QDoc3 generates tables with wrong number of columns. We have to
//check and if necessary, merge the last columns.
qsizetype maxCols = -1;
- for (const auto &row : qAsConst(m_rows)) {
+ for (const auto &row : std::as_const(m_rows)) {
if (row.size() > maxCols)
maxCols = row.size();
}
@@ -1489,13 +1585,11 @@ void QtXmlToSphinx::Table::format(TextStream& s) const
// print line
s << '+';
for (qsizetype col = 0; col < headerColumnCount; ++col) {
- char c;
+ char c = '-';
if (col >= row.size() || row[col].rowSpan == -1)
c = ' ';
else if (i == 1 && hasHeader())
c = '=';
- else
- c = '-';
s << Pad(c, colWidths.at(col)) << '+';
}
s << '\n';
diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
index bb58c0878..398c5bc97 100644
--- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
+++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
@@ -6,14 +6,11 @@
#include <textstream.h>
-#include "qtcompat.h"
-
-#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QScopedPointer>
-#include <QtCore/QSharedPointer>
#include <QtCore/QStack>
-#include <QtCore/QTextStream>
+
+#include <memory>
QT_BEGIN_NAMESPACE
class QDebug;
@@ -73,14 +70,9 @@ public:
return m_normalized;
}
- void clear() {
- m_normalized = false;
- m_rows.clear();
- }
-
void appendRow(const TableRow &row) { m_rows.append(row); }
- const TableRow &constFirst() { return m_rows.constFirst(); }
+ const TableRow &constFirst() const { return m_rows.constFirst(); }
TableRow &first() { return m_rows.first(); }
TableRow &last() { return m_rows.last(); }
@@ -109,8 +101,12 @@ public:
static void stripPythonQualifiers(QString *s);
+ // For testing
+ static QString readSnippet(QIODevice &inputFile, const QString &identifier,
+ QString *errorMessage);
+
private:
- using StringSharedPtr = QSharedPointer<QString>;
+ using StringSharedPtr = std::shared_ptr<QString>;
QString transform(const QString& doc);
@@ -164,7 +160,7 @@ private:
QStack<StringSharedPtr> m_buffers; // Maintain address stability since it used in TextStream
- Table m_currentTable;
+ QStack<Table> m_tables; // Stack of tables, used for <table><list> with nested <item>
QScopedPointer<QtXmlToSphinxLink> m_linkContext; // for <link>
QScopedPointer<QtXmlToSphinxLink> m_seeAlsoContext; // for <see-also>foo()</see-also>
QString m_context;
@@ -177,6 +173,8 @@ private:
QString m_opened_anchor;
QList<InlineImage> m_inlineImages;
+ bool m_containsAutoTranslations = false;
+
struct Snippet
{
enum Result {
@@ -190,10 +188,12 @@ private:
Result result;
};
+ void setAutoTranslatedNote(QString *str) const;
+
Snippet readSnippetFromLocations(const QString &path,
const QString &identifier,
const QString &fallbackPath,
- QString *errorMessage) const;
+ QString *errorMessage);
static QString readFromLocation(const QString &location, const QString &identifier,
QString *errorMessage);
void pushOutputBuffer();
diff --git a/sources/shiboken6/generator/qtdoc/rstformat.h b/sources/shiboken6/generator/qtdoc/rstformat.h
index 6e97c5fcd..8af7671fb 100644
--- a/sources/shiboken6/generator/qtdoc/rstformat.h
+++ b/sources/shiboken6/generator/qtdoc/rstformat.h
@@ -30,28 +30,6 @@ inline QByteArray rstDeprecationNote(const char *what)
+ what + QByteArrayLiteral(" is deprecated.\n\n");
}
-class Pad
-{
-public:
- explicit Pad(char c, int count) : m_char(c), m_count(count) {}
-
- void write(TextStream &str) const
- {
- for (int i = 0; i < m_count; ++i)
- str << m_char;
- }
-
-private:
- const char m_char;
- const int m_count;
-};
-
-inline TextStream &operator<<(TextStream &str, const Pad &pad)
-{
- pad.write(str);
- return str;
-}
-
template <class String>
inline int writeEscapedRstText(TextStream &str, const String &s)
{
diff --git a/sources/shiboken6/generator/shiboken/configurablescope.h b/sources/shiboken6/generator/shiboken/configurablescope.h
new file mode 100644
index 000000000..9040c7ad9
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/configurablescope.h
@@ -0,0 +1,33 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CONFIGURABLESCOPE_H
+#define CONFIGURABLESCOPE_H
+
+#include <textstream.h>
+#include <configurabletypeentry.h>
+
+/// Enclose a scope within preprocessor conditions for configurable entries
+class ConfigurableScope
+{
+public:
+ explicit ConfigurableScope(TextStream &s, const ConfigurableTypeEntryCPtr &t) :
+ m_stream(s),
+ m_hasConfigCondition(t->hasConfigCondition())
+ {
+ if (m_hasConfigCondition)
+ m_stream << t->configCondition() << '\n';
+ }
+
+ ~ConfigurableScope()
+ {
+ if (m_hasConfigCondition)
+ m_stream << "#endif\n";
+ }
+
+private:
+ TextStream &m_stream;
+ const bool m_hasConfigCondition;
+};
+
+#endif // CONFIGURABLESCOPE_H
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 884a531f6..48e7f4fe5 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -2,9 +2,14 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppgenerator.h"
+#include "configurablescope.h"
+#include "generatorargument.h"
+#include "generatorstrings.h"
+#include "defaultvalue.h"
+#include "generatorcontext.h"
#include "codesnip.h"
+#include "customconversion.h"
#include "headergenerator.h"
-#include "apiextractor.h"
#include "apiextractorresult.h"
#include "ctypenames.h"
#include <exception.h>
@@ -32,6 +37,7 @@
#include <primitivetypeentry.h>
#include <smartpointertypeentry.h>
#include <typesystemtypeentry.h>
+#include <valuetypeentry.h>
#include <parser/enumvalue.h>
#include "qtcompat.h"
@@ -46,38 +52,54 @@
#include <algorithm>
#include <cstring>
#include <memory>
+#include <set>
using namespace Qt::StringLiterals;
-static const QString CPP_ARG0 = u"cppArg0"_s;
-const char *CppGenerator::PYTHON_TO_CPPCONVERSION_STRUCT = "Shiboken::Conversions::PythonToCppConversion";
+static const char shibokenErrorsOccurred[] = "Shiboken::Errors::occurred() != nullptr";
-static inline QString reprFunction() { return QStringLiteral("__repr__"); }
+static constexpr auto virtualMethodStaticReturnVar = "result"_L1;
-static const char typeNameFunc[] = R"CPP(template <class T>
-static const char *typeNameOf(const T &t)
+static constexpr auto sbkObjectTypeF = "SbkObject_TypeF()"_L1;
+static const char initInheritanceFunction[] = "initInheritance";
+
+static QString mangleName(QString name)
{
- const char *typeName = typeid(t).name();
- auto size = std::strlen(typeName);
-#if defined(Q_CC_MSVC) // MSVC: "class QPaintDevice * __ptr64"
- if (auto lastStar = strchr(typeName, '*')) {
- // MSVC: "class QPaintDevice * __ptr64"
- while (*--lastStar == ' ') {
- }
- size = lastStar - typeName + 1;
- }
-#else // g++, Clang: "QPaintDevice *" -> "P12QPaintDevice"
- if (size > 2 && typeName[0] == 'P' && std::isdigit(typeName[1])) {
- ++typeName;
- --size;
- }
-#endif
- char *result = new char[size + 1];
- result[size] = '\0';
- memcpy(result, typeName, size);
- return result;
+ if (name == u"None" || name == u"False" || name == u"True" || name == u"from")
+ name += u'_';
+ return name;
+}
+
+struct sbkUnusedVariableCast
+{
+ explicit sbkUnusedVariableCast(QAnyStringView name) : m_name(name) {}
+
+ const QAnyStringView m_name;
+};
+
+TextStream &operator<<(TextStream &str, const sbkUnusedVariableCast &c)
+{
+ str << "SBK_UNUSED(" << c.m_name << ")\n";
+ return str;
+}
+
+struct pyTypeGetSlot
+{
+ explicit pyTypeGetSlot(QAnyStringView funcType, QAnyStringView typeObject,
+ QAnyStringView aSlot) :
+ m_funcType(funcType), m_typeObject(typeObject), m_slot(aSlot) {}
+
+ const QAnyStringView m_funcType;
+ const QAnyStringView m_typeObject;
+ const QAnyStringView m_slot;
+};
+
+TextStream &operator<<(TextStream &str, const pyTypeGetSlot &p)
+{
+ str << "reinterpret_cast<" << p.m_funcType << ">(PepType_GetSlot("
+ << p.m_typeObject << ", " << p.m_slot << "));\n";
+ return str;
}
-)CPP";
TextStream &operator<<(TextStream &s, CppGenerator::ErrorReturn r)
{
@@ -99,6 +121,25 @@ TextStream &operator<<(TextStream &s, CppGenerator::ErrorReturn r)
return s;
}
+static constexpr auto converterVar = "converter"_L1;
+
+struct registerConverterName
+{
+ explicit registerConverterName(QAnyStringView typeName,
+ QAnyStringView varName = converterVar) :
+ m_typeName(typeName), m_varName(varName) {}
+
+ QAnyStringView m_typeName;
+ QAnyStringView m_varName;
+};
+
+TextStream &operator<<(TextStream &s, const registerConverterName &r)
+{
+ s << "Shiboken::Conversions::registerConverterName(" << r.m_varName
+ << ", \"" << r.m_typeName << "\");\n";
+ return s;
+}
+
// Protocol function name / function parameters / return type
struct ProtocolEntry
{
@@ -131,7 +172,7 @@ const ProtocolEntries &mappingProtocols()
u"PyObject*"_s},
{u"__msetitem__"_s,
u"PyObject *self, PyObject *_key, PyObject *_value"_s,
- intT()}};
+ intT}};
return result;
}
@@ -148,16 +189,16 @@ const ProtocolEntries &sequenceProtocols()
u"PyObject*"_s},
{u"__setitem__"_s,
u"PyObject *self, Py_ssize_t _i, PyObject *_value"_s,
- intT()},
+ intT},
{u"__getslice__"_s,
u"PyObject *self, Py_ssize_t _i1, Py_ssize_t _i2"_s,
u"PyObject*"_s},
{u"__setslice__"_s,
u"PyObject *self, Py_ssize_t _i1, Py_ssize_t _i2, PyObject *_value"_s,
- intT()},
+ intT},
{u"__contains__"_s,
u"PyObject *self, PyObject *_value"_s,
- intT()},
+ intT},
{u"__concat__"_s,
u"PyObject *self, PyObject *_other"_s,
u"PyObject*"_s}
@@ -168,14 +209,14 @@ const ProtocolEntries &sequenceProtocols()
// Return name of function to create PyObject wrapping a container
static QString opaqueContainerCreationFunc(const AbstractMetaType &type)
{
- const auto *containerTypeEntry =
- static_cast<const ContainerTypeEntry *>(type.typeEntry());
- const auto *instantiationTypeEntry =
+ const auto containerTypeEntry =
+ std::static_pointer_cast<const ContainerTypeEntry>(type.typeEntry());
+ const auto instantiationTypeEntry =
type.instantiations().constFirst().typeEntry();
QString result = u"create"_s;
if (type.isConstant())
result += u"Const"_s;
- result += containerTypeEntry->opaqueContainerName(instantiationTypeEntry->name());
+ result += containerTypeEntry->opaqueContainerName(type.instantiationCppSignatures());
return result;
}
@@ -195,135 +236,16 @@ QString CppGenerator::fileNameForContext(const GeneratorContext &context) const
return fileNameForContextHelper(context, u"_wrapper.cpp"_s);
}
-static bool isInplaceAdd(const AbstractMetaFunctionCPtr &func)
-{
- return func->name() == u"operator+=";
-}
-
-static bool isIncrementOperator(const AbstractMetaFunctionCPtr &func)
-{
- return func->functionType() == AbstractMetaFunction::IncrementOperator;
-}
-
-static bool isDecrementOperator(const AbstractMetaFunctionCPtr &func)
-{
- return func->functionType() == AbstractMetaFunction::DecrementOperator;
-}
-
-// Filter predicate for operator functions
-static bool skipOperatorFunc(const AbstractMetaFunctionCPtr &func)
-{
- if (func->isModifiedRemoved() || func->usesRValueReferences())
- return true;
- const auto &name = func->name();
- return name == u"operator[]" || name == u"operator->" || name == u"operator!";
-}
-
-QList<AbstractMetaFunctionCList>
- CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass *metaClass,
- OperatorQueryOptions query)
-{
- // ( func_name, num_args ) => func_list
- QMap<QPair<QString, int>, AbstractMetaFunctionCList> results;
-
- auto funcs = metaClass->operatorOverloads(query);
- auto end = std::remove_if(funcs.begin(), funcs.end(), skipOperatorFunc);
- funcs.erase(end, funcs.end());
-
- // If we have operator+=, we remove the operator++/-- which would
- // otherwise be used for emulating __iadd__, __isub__.
- if (std::any_of(funcs.cbegin(), funcs.cend(), isInplaceAdd)) {
- end = std::remove_if(funcs.begin(), funcs.end(),
- [] (const AbstractMetaFunctionCPtr &func) {
- return func->isIncDecrementOperator();
- });
- funcs.erase(end, funcs.end());
- } else {
- // If both prefix/postfix ++/-- are present, remove one
- if (std::count_if(funcs.begin(), funcs.end(), isIncrementOperator) > 1)
- funcs.erase(std::find_if(funcs.begin(), funcs.end(), isIncrementOperator));
- if (std::count_if(funcs.begin(), funcs.end(), isDecrementOperator) > 1)
- funcs.erase(std::find_if(funcs.begin(), funcs.end(), isDecrementOperator));
- }
-
- for (const auto &func : funcs) {
- int args;
- if (func->isComparisonOperator()) {
- args = -1;
- } else {
- args = func->arguments().size();
- }
- QPair<QString, int > op(func->name(), args);
- results[op].append(func);
- }
- QList<AbstractMetaFunctionCList> result;
- result.reserve(results.size());
- for (auto it = results.cbegin(), end = results.cend(); it != end; ++it)
- result.append(it.value());
- return result;
-}
-
-CppGenerator::BoolCastFunctionOptional
- CppGenerator::boolCast(const AbstractMetaClass *metaClass) const
-{
- const auto *te = metaClass->typeEntry();
- if (te->isSmartPointer()) {
- auto *ste = static_cast<const SmartPointerTypeEntry *>(te);
-
- auto valueCheckMethod = ste->valueCheckMethod();
- if (!valueCheckMethod.isEmpty()) {
- const auto func = metaClass->findFunction(valueCheckMethod);
- if (func.isNull())
- throw Exception(msgMethodNotFound(metaClass, valueCheckMethod));
- return BoolCastFunction{func, false};
- }
-
- auto nullCheckMethod = ste->nullCheckMethod();
- if (!nullCheckMethod.isEmpty()) {
- const auto func = metaClass->findFunction(nullCheckMethod);
- if (func.isNull())
- throw Exception(msgMethodNotFound(metaClass, nullCheckMethod));
- return BoolCastFunction{func, true};
- }
- }
-
- auto mode = te->operatorBoolMode();
- if (useOperatorBoolAsNbNonZero()
- ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
- const auto func = metaClass->findOperatorBool();
- if (!func.isNull())
- return BoolCastFunction{func, false};
- }
-
- mode = te->isNullMode();
- if (useIsNullAsNbNonZero()
- ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
- const auto func = metaClass->findQtIsNullMethod();
- if (!func.isNull())
- return BoolCastFunction{func, true};
- }
- return std::nullopt;
-}
-
-std::optional<AbstractMetaType>
- CppGenerator::findSmartPointerInstantiation(const SmartPointerTypeEntry *pointer,
- const TypeEntry *pointee) const
-{
- for (const auto &smp : api().instantiatedSmartPointers()) {
- const auto &i = smp.type;
- if (i.typeEntry() == pointer && i.instantiations().at(0).typeEntry() == pointee)
- return i;
- }
- return {};
-}
-
void CppGenerator::clearTpFuncs()
{
+ // Functions that should not be registered under a name in PyMethodDef,
+ // but under a special constant under slots.
m_tpFuncs = {
{u"__str__"_s, {}}, {u"__str__"_s, {}},
- {reprFunction(), {}}, {u"__iter__"_s, {}},
+ {REPR_FUNCTION, {}}, {u"__iter__"_s, {}},
{u"__next__"_s, {}}
};
+ m_nbFuncs = { {u"__abs__"_s, {}}, {u"__pow__"_s, {} }};
}
// Prevent ELF symbol qt_version_tag from being generated into the source
@@ -333,7 +255,7 @@ static const char includeQDebug[] =
"#endif\n"
"#include <QtCore/QDebug>\n";
-static QString chopType(QString s)
+QString CppGenerator::chopType(QString s)
{
if (s.endsWith(u"_Type"))
s.chop(5);
@@ -367,18 +289,121 @@ static QString buildPropertyString(const QPropertySpec &spec)
return text;
}
+static QString _plainName(const QString &s)
+{
+ auto cutPos = s.lastIndexOf(u"::"_s);
+ return cutPos < 0 ? s : s.right(s.length() - (cutPos + 2));
+}
+
+/**********************************************************************
+ *
+ * Decision whether to use an IntEnum/IntFlag
+ * ------------------------------------------
+ *
+ * Unfortunately, all attempts to drive this decision automagically
+ * did not work out. We therefore compile a list in with known
+ * IntEnum and IntFlag.
+ */
+
+/*
+ * This function is now unused and replaced by TypeSystem::PythonEnumType
+ */
+#if 0
+static QSet<QString> useIntSet()
+{
+ static const QSet<QString> result{
+ /* IntEnum */ u"PySide6.QtCore.QDataStream.Version"_s,
+ /* IntEnum */ u"PySide6.QtCore.QEvent.Type"_s,
+ /* IntEnum */ u"PySide6.QtCore.QLocale.FloatingPointPrecisionOption"_s,
+ /* IntFlag */ u"PySide6.QtCore.QLocale.LanguageCodeType"_s,
+ /* IntFlag */ u"PySide6.QtCore.QUrl.ComponentFormattingOption"_s,
+ // note: "QUrl::UrlFormattingOption" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtCore.QUrl.UrlFormattingOption"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.AlignmentFlag"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.FocusPolicy"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.GestureType"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.ItemDataRole"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.Key"_s,
+ /* Flag */ u"PySide6.QtCore.Qt.Modifier"_s,
+ // note: "Qt::TextFlag" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtCore.Qt.TextFlag"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.WindowType"_s,
+ // This is found in QtWidgets but should be in QtGui.
+ /* IntEnum */ u"PySide6.QtGui.QFileSystemModel.Roles"_s,
+ /* IntEnum */ u"PySide6.QtGui.QFont.Stretch"_s,
+ /* IntEnum */ u"PySide6.QtGui.QFont.Weight"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextDocument.ResourceType"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.FormatType"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.ObjectTypes"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.Property"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QDialog.DialogCode"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QFrame.Shadow"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QFrame.Shape"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QListWidgetItem.ItemType"_s,
+ /* IntFlag */ u"PySide6.QtWidgets.QMessageBox.StandardButton"_s,
+ // note: "QSizePolicy::PolicyFlag" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtWidgets.QSizePolicy.PolicyFlag"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ComplexControl"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ContentsType"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ControlElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.PixelMetric"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.PrimitiveElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.StandardPixmap"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.StyleHint"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.SubElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QTableWidgetItem.ItemType"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QTreeWidgetItem.ItemType"_s,
+ /* IntEnum */ u"PySide6.QtCharts.QBoxSet.ValuePositions"_s,
+ /* IntEnum */ u"PySide6.QtMultimedia.QMediaPlayer.Loops"_s,
+ /* IntEnum */ u"PySide6.QtQuick.QSGGeometry.DrawingMode"_s,
+ /* IntEnum */ u"PySide6.QtWebEngineCore.QWebEngineScript.ScriptWorldId"_s,
+ // Added because it should really be used as number
+ /* IntEnum */ u"PySide6.QtCore.QMetaType.Type"_s,
+ /* IntEnum */ u"PySide6.QtSerialPort.QSerialPort.BaudRate"_s,
+ };
+ return result;
+}
+#endif
+
+static bool _shouldInheritInt(const AbstractMetaEnum &cppEnum)
+{
+ return !cppEnum.fullName().startsWith(u"PySide6."_s);
+}
+
+static QString BuildEnumFlagInfo(const AbstractMetaEnum &cppEnum)
+{
+ auto enumType = cppEnum.typeEntry();
+ QString result = _plainName(enumType->name());
+ auto flags = enumType->flags();
+ auto decision = enumType->pythonEnumType();
+ bool _int = _shouldInheritInt(cppEnum);
+ bool _flag = bool(flags);
+
+ if (decision != TypeSystem::PythonEnumType::Unspecified) {
+ _int = decision == TypeSystem::PythonEnumType::IntEnum ||
+ decision == TypeSystem::PythonEnumType::IntFlag;
+ _flag = decision == TypeSystem::PythonEnumType::Flag ||
+ decision == TypeSystem::PythonEnumType::IntFlag;
+ }
+ result += _flag ? (_int ? u":IntFlag"_s : u":Flag"_s)
+ : (_int ? u":IntEnum"_s : u":Enum"_s);
+ if (flags)
+ result += u':' + _plainName(flags->flagsName());
+ return u'"' + result + u'"';
+}
+
static void writePyGetSetDefEntry(TextStream &s, const QString &name,
const QString &getFunc, const QString &setFunc)
{
- s << "{const_cast<char *>(\"" << name << "\"), " << getFunc << ", "
- << (setFunc.isEmpty() ? NULL_PTR : setFunc) << "},\n";
+ s << "{const_cast<char *>(\"" << mangleName(name) << "\"), " << getFunc << ", "
+ << (setFunc.isEmpty() ? NULL_PTR : setFunc) << ", nullptr, nullptr},\n";
}
static bool generateRichComparison(const GeneratorContext &c)
{
- auto *metaClass = c.metaClass();
+ const auto metaClass = c.metaClass();
if (c.forSmartPointer()) {
- auto *te = static_cast<const SmartPointerTypeEntry *>(metaClass->typeEntry());
+ auto te = std::static_pointer_cast<const SmartPointerTypeEntry>(metaClass->typeEntry());
return te->smartPointerType() == TypeSystem::SmartPointerType::Shared;
}
@@ -389,17 +414,16 @@ void CppGenerator::generateIncludes(TextStream &s, const GeneratorContext &class
const IncludeGroupList &includes,
const AbstractMetaClassCList &innerClasses) const
{
- const AbstractMetaClass *metaClass = classContext.metaClass();
+ const auto metaClass = classContext.metaClass();
// write license comment
s << licenseComment() << '\n';
const bool normalClass = !classContext.forSmartPointer();
- if (normalClass && !avoidProtectedHack() && !metaClass->isNamespace()
- && !metaClass->hasPrivateDestructor()) {
- s << "//workaround to access protected functions\n";
- s << "#define protected public\n\n";
- }
+ // Normally only required for classes for which we want to generate protected API,
+ // but it needs to be generated into all files to ensure ODR for Unity builds.
+ if (!avoidProtectedHack())
+ s << HeaderGenerator::protectedHackDefine;
QByteArrayList cppIncludes{"typeinfo", "iterator", // for containers
"cctype", "cstring"};
@@ -413,7 +437,9 @@ void CppGenerator::generateIncludes(TextStream &s, const GeneratorContext &class
if (normalClass && usePySideExtensions()) {
s << includeQDebug;
- if (metaClass->isQObject()) {
+ if (metaClass->hasToStringCapability())
+ s << "#include <QtCore/QBuffer>\n";
+ if (isQObject(metaClass)) {
s << "#include <pysideqobject.h>\n"
<< "#include <pysidesignal.h>\n"
<< "#include <pysideproperty.h>\n"
@@ -443,58 +469,60 @@ void CppGenerator::generateIncludes(TextStream &s, const GeneratorContext &class
if (!innerClasses.isEmpty()) {
s << "\n// inner classes\n";
- for (const AbstractMetaClass *innerClass : innerClasses) {
+ for (const auto &innerClass : innerClasses) {
GeneratorContext innerClassContext = contextForClass(innerClass);
s << "#include \""
<< HeaderGenerator::headerFileNameForContext(innerClassContext) << "\"\n";
}
}
+ if (avoidProtectedHack())
+ s << baseWrapperIncludes(classContext);
+
for (const auto &g : includes)
s << g;
// C++ includes
std::sort(cppIncludes.begin(), cppIncludes.end());
s << '\n';
- for (const auto &i : qAsConst(cppIncludes))
+ for (const auto &i : std::as_const(cppIncludes))
s << "#include <" << i << ">\n";
}
-static const char openTargetExternC[] = R"(
-// Target ---------------------------------------------------------
-
-extern "C" {
-)";
-
-static const char closeExternC[] = "} // extern \"C\"\n\n";
-
// Write methods definition
-static void writePyMethodDefs(TextStream &s, const QString &className,
- const QString &methodsDefinitions, bool generateCopy)
+void CppGenerator::writePyMethodDefs(TextStream &s, const QString &className,
+ const QString &methodsDefinitions)
{
s << "static PyMethodDef " << className << "_methods[] = {\n" << indent
- << methodsDefinitions << '\n';
- if (generateCopy) {
- s << "{\"__copy__\", reinterpret_cast<PyCFunction>(" << className << "___copy__)"
- << ", METH_NOARGS},\n";
+ << methodsDefinitions << METHOD_DEF_SENTINEL << outdent << "};\n\n";
+}
+
+void CppGenerator::writeModuleCodeSnips(TextStream &s, const CodeSnipList &codeSnips,
+ TypeSystem::CodeSnipPosition position,
+ TypeSystem::Language language) const
+{
+ if (!codeSnips.isEmpty()) {
+ try {
+ writeCodeSnips(s, codeSnips, position, language);
+ } catch (const std::exception &e) {
+ throw Exception(msgSnippetError("module source of "_L1 + moduleName(), e.what()));
+ }
}
- s << '{' << NULL_PTR << ", " << NULL_PTR << "} // Sentinel\n" << outdent
- << "};\n\n";
}
-static bool hasHashFunction(const AbstractMetaClass *c)
+bool CppGenerator::hasHashFunction(const AbstractMetaClassCPtr &c)
{
return !c->typeEntry()->hashFunction().isEmpty()
|| c->hasHashFunction();
}
-static bool needsTypeDiscoveryFunction(const AbstractMetaClass *c)
+static bool needsTypeDiscoveryFunction(const AbstractMetaClassCPtr &c)
{
return c->baseClass() != nullptr
&& (c->isPolymorphic() || !c->typeEntry()->polymorphicIdValue().isEmpty());
}
-static void writeAddedTypeSignatures(TextStream &s, const ComplexTypeEntry *te)
+static void writeAddedTypeSignatures(TextStream &s, const ComplexTypeEntryCPtr &te)
{
for (const auto &e : te->addedPyMethodDefEntrys()) {
if (auto count = e.signatures.size()) {
@@ -518,12 +546,12 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
}
s.setLanguage(TextStream::Language::Cpp);
- const AbstractMetaClass *metaClass = classContext.metaClass();
- const auto *typeEntry = metaClass->typeEntry();
+ AbstractMetaClassCPtr metaClass = classContext.metaClass();
+ const auto typeEntry = metaClass->typeEntry();
auto innerClasses = metaClass->innerClasses();
for (auto it = innerClasses.begin(); it != innerClasses.end(); ) {
- auto *innerTypeEntry = (*it)->typeEntry();
+ auto innerTypeEntry = (*it)->typeEntry();
if (shouldGenerate(innerTypeEntry) && !innerTypeEntry->isSmartPointer())
++it;
else
@@ -533,20 +561,9 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
AbstractMetaEnumList classEnums = metaClass->enums();
metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
- //Extra includes
IncludeGroupList includeGroups;
- if (!classContext.useWrapper()) {
- includeGroups.append(IncludeGroup{u"Extra includes"_s,
- typeEntry->extraIncludes()});
- }
-
- includeGroups.append(IncludeGroup{u"Argument includes"_s,
- typeEntry->argumentIncludes()});
-
- includeGroups.append(IncludeGroup{u"Enum includes"_s, {}});
- for (const AbstractMetaEnum &cppEnum : qAsConst(classEnums))
- includeGroups.back().includes.append(cppEnum.typeEntry()->extraIncludes());
-
+ if (!classContext.useWrapper() || !avoidProtectedHack())
+ includeGroups.append(classIncludes(metaClass));
generateIncludes(s, classContext, includeGroups, innerClasses);
if (typeEntry->typeFlags().testFlag(ComplexTypeEntry::Deprecated))
@@ -554,10 +571,10 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
// Use class base namespace
{
- const AbstractMetaClass *context = metaClass->enclosingClass();
+ AbstractMetaClassCPtr context = metaClass->enclosingClass();
while (context) {
if (context->isNamespace() && !context->enclosingClass()
- && static_cast<const NamespaceTypeEntry *>(context->typeEntry())->generateUsing()) {
+ && std::static_pointer_cast<const NamespaceTypeEntry>(context->typeEntry())->generateUsing()) {
s << "\nusing namespace " << context->qualifiedCppName() << ";\n";
break;
}
@@ -565,7 +582,7 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
}
}
- s << '\n' << typeNameFunc << '\n';
+ s << '\n';
// class inject-code native/beginning
if (!typeEntry->codeSnips().isEmpty()) {
@@ -576,19 +593,22 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
}
// python conversion rules
- if (typeEntry->hasTargetConversionRule()) {
- s << "// Python Conversion\n";
- s << typeEntry->targetConversionRule() << '\n';
+ if (typeEntry->isValue()) {
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry);
+ if (vte->hasTargetConversionRule()) {
+ s << "// Python Conversion\n";
+ s << vte->targetConversionRule() << '\n';
+ }
}
if (classContext.useWrapper()) {
s << "// Native ---------------------------------------------------------\n\n";
if (avoidProtectedHack() && usePySideExtensions()) {
- s << "void " << classContext.wrapperName() << "::pysideInitQtMetaTypes()\n{\n";
- Indentation indent(s);
+ s << "void " << classContext.wrapperName() << "::pysideInitQtMetaTypes()\n{\n"
+ << indent;
writeInitQtMetaTypeFunctionBody(s, classContext);
- s << "}\n\n";
+ s << outdent << "}\n\n";
}
int maxOverrides = 0;
@@ -601,13 +621,15 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
writeVirtualMethodNative(s, func, maxOverrides++);
}
- if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) {
- if (usePySideExtensions() && metaClass->isQObject())
- writeMetaObjectMethod(s, classContext);
+ if (shouldGenerateMetaObjectFunctions(metaClass))
+ writeMetaObjectMethod(s, classContext);
+ if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
writeDestructorNative(s, classContext);
- }
}
+ for (const auto &f : metaClass->userAddedPythonOverrides())
+ writeUserAddedPythonOverride(s, f);
+
StringStream smd(TextStream::Language::Cpp);
StringStream md(TextStream::Language::Cpp);
StringStream signatureStream(TextStream::Language::Cpp);
@@ -647,22 +669,22 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
smd << "static PyMethodDef " << methDefName << " = " << indent
<< defEntries.constFirst() << outdent << ";\n\n";
}
- if (!m_tpFuncs.contains(rfunc->name()))
+ const auto &fname = rfunc->name();
+ if (!m_tpFuncs.contains(fname) && !m_nbFuncs.contains(fname))
md << defEntries;
}
}
for (const auto &pyMethodDef : typeEntry->addedPyMethodDefEntrys())
md << pyMethodDef << ",\n";
+
+ if (typeEntry->isValue())
+ writeCopyFunction(s, md, signatureStream, classContext);
+
const QString methodsDefinitions = md.toString();
const QString singleMethodDefinitions = smd.toString();
const QString className = chopType(cpythonTypeName(metaClass));
- if (typeEntry->isValue()) {
- writeCopyFunction(s, classContext);
- signatureStream << fullPythonClassName(metaClass) << ".__copy__()\n";
- }
-
// Write single method definitions
s << singleMethodDefinitions;
@@ -678,14 +700,27 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
s << '\n';
s << "static const char *" << className << "_PropertyStrings[] = {\n" << indent;
- for (const auto &entry : qAsConst(sorter))
+ for (const auto &entry : std::as_const(sorter))
+ s << entry << ",\n";
+ s << NULL_PTR << " // Sentinel\n"
+ << outdent << "};\n\n";
+
+ }
+ // PYSIDE-1735: Write an EnumFlagInfo structure
+ QStringList sorter;
+ for (const auto &entry : std::as_const(classEnums))
+ sorter.append(BuildEnumFlagInfo(entry));
+ sorter.sort();
+ if (!sorter.empty()) {
+ s << "static const char *" << className << "_EnumFlagInfo[] = {\n" << indent;
+ for (const auto &entry : std::as_const(sorter))
s << entry << ",\n";
s << NULL_PTR << " // Sentinel\n"
<< outdent << "};\n\n";
}
// Write methods definition
- writePyMethodDefs(s, className, methodsDefinitions, typeEntry->isValue());
+ writePyMethodDefs(s, className, methodsDefinitions);
// Write tp_s/getattro function
const AttroCheck attroCheck = checkAttroFunctionNeeds(metaClass);
@@ -698,25 +733,8 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
writeNbBoolFunction(classContext, f.value(), s);
if (supportsNumberProtocol(metaClass)) {
- const QList<AbstractMetaFunctionCList> opOverloads = filterGroupedOperatorFunctions(
- metaClass,
- OperatorQueryOption::ArithmeticOp
- | OperatorQueryOption::IncDecrementOp
- | OperatorQueryOption::LogicalOp
- | OperatorQueryOption::BitwiseOp);
-
- for (const AbstractMetaFunctionCList &allOverloads : opOverloads) {
- AbstractMetaFunctionCList overloads;
- for (const auto &func : allOverloads) {
- if (!func->isModifiedRemoved()
- && !func->isPrivate()
- && (func->ownerClass() == func->implementingClass() || func->isAbstract()))
- overloads.append(func);
- }
-
- if (overloads.isEmpty())
- continue;
-
+ const auto numberProtocolOps = numberProtocolOperators(metaClass);
+ for (const auto &overloads : numberProtocolOps) {
OverloadData overloadData(overloads, api());
writeMethodWrapper(s, overloadData, classContext);
writeSignatureInfo(signatureStream, overloadData);
@@ -779,7 +797,7 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
cpythonGetterFunctionName(property, metaClass), setter);
}
}
- s << '{' << NULL_PTR << "} // Sentinel\n"
+ s << "{nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel\n"
<< outdent << "};\n\n";
}
@@ -795,11 +813,10 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
writeClassDefinition(s, metaClass, classContext);
s << '\n';
- if (needsTypeDiscoveryFunction(metaClass))
+ if (needsTypeDiscoveryFunction(metaClass)) {
writeTypeDiscoveryFunction(s, metaClass);
-
- writeFlagsNumberMethodsDefinitions(s, classEnums);
- s << '\n';
+ s << '\n';
+ }
writeConverterFunctions(s, metaClass, classContext);
writeAddedTypeSignatures(signatureStream, typeEntry);
@@ -817,145 +834,6 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
}
}
-static bool hasParameterPredicate(const AbstractMetaFunctionCPtr &f)
-{
- return !f->arguments().isEmpty();
-}
-
-void CppGenerator::generateSmartPointerClass(TextStream &s, const GeneratorContext &classContext)
-{
- s.setLanguage(TextStream::Language::Cpp);
- const AbstractMetaClass *metaClass = classContext.metaClass();
- const auto *typeEntry = static_cast<const SmartPointerTypeEntry *>(metaClass->typeEntry());
- const bool hasPointeeClass = classContext.pointeeClass() != nullptr;
- const auto smartPointerType = typeEntry->smartPointerType();
- const bool isValueHandle = smartPointerType ==TypeSystem::SmartPointerType::ValueHandle;
-
- IncludeGroup includes{u"Extra includes"_s, typeEntry->extraIncludes()};
- generateIncludes(s, classContext, {includes});
-
- s << '\n' << typeNameFunc << '\n';
-
- // Create string literal for smart pointer getter method.
- QString rawGetter = typeEntry->getter();
- s << "static const char " << SMART_POINTER_GETTER << "[] = \"" << rawGetter << "\";";
-
- // class inject-code native/beginning
- if (!typeEntry->codeSnips().isEmpty()) {
- writeClassCodeSnips(s, typeEntry->codeSnips(),
- TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode,
- classContext);
- s << '\n';
- }
-
- StringStream smd(TextStream::Language::Cpp);
- StringStream md(TextStream::Language::Cpp);
- StringStream signatureStream(TextStream::Language::Cpp);
-
- s << openTargetExternC;
-
- const auto &functionGroups = getFunctionGroups(metaClass);
-
- // Skip all public methods of the smart pointer except for the special
- // methods declared in the type entry.
-
- auto ctors = metaClass->queryFunctions(FunctionQueryOption::Constructors);
- if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
- auto end = std::remove_if(ctors.begin(), ctors.end(), hasParameterPredicate);
- ctors.erase(end, ctors.end());
- }
-
- if (!ctors.isEmpty()) {
- OverloadData overloadData(ctors, api());
- writeConstructorWrapper(s, overloadData, classContext);
- writeSignatureInfo(signatureStream, overloadData);
- }
-
- if (!typeEntry->resetMethod().isEmpty()) {
- auto it = functionGroups.constFind(typeEntry->resetMethod());
- if (it == functionGroups.cend())
- throw Exception(msgCannotFindSmartPointerMethod(typeEntry, typeEntry->resetMethod()));
- AbstractMetaFunctionCList resets = it.value();
- if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
- auto end = std::remove_if(resets.begin(), resets.end(), hasParameterPredicate);
- resets.erase(end, resets.end());
- }
- if (!resets.isEmpty())
- writeMethodWrapper(s, md, signatureStream, resets, classContext);
- }
-
- auto it = functionGroups.constFind(rawGetter);
- if (it == functionGroups.cend() || it.value().size() != 1)
- throw Exception(msgCannotFindSmartPointerGetter(typeEntry));
-
- writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
-
- QStringList optionalMethods;
- if (!typeEntry->refCountMethodName().isEmpty())
- optionalMethods.append(typeEntry->refCountMethodName());
- const QString valueCheckMethod = typeEntry->valueCheckMethod();
- if (!valueCheckMethod.isEmpty() && !valueCheckMethod.startsWith(u"operator"))
- optionalMethods.append(valueCheckMethod);
- if (!typeEntry->nullCheckMethod().isEmpty())
- optionalMethods.append(typeEntry->nullCheckMethod());
-
- for (const QString &optionalMethod : optionalMethods) {
- auto it = functionGroups.constFind(optionalMethod);
- if (it == functionGroups.cend() || it.value().size() != 1)
- throw Exception(msgCannotFindSmartPointerMethod(typeEntry, optionalMethod));
- writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
- }
-
- const QString methodsDefinitions = md.toString();
- const QString singleMethodDefinitions = smd.toString();
-
- const QString className = chopType(cpythonTypeName(typeEntry));
-
- writeCopyFunction(s, classContext);
- signatureStream << fullPythonClassName(metaClass) << ".__copy__()\n";
-
- // Write single method definitions
- s << singleMethodDefinitions;
-
- // Write methods definition
- writePyMethodDefs(s, className, methodsDefinitions, true /* ___copy__ */);
-
- // Write tp_s/getattro function
- const auto boolCastOpt = boolCast(metaClass);
- writeSmartPointerGetattroFunction(s, classContext, boolCastOpt);
- writeSmartPointerSetattroFunction(s, classContext);
-
- if (boolCastOpt.has_value())
- writeNbBoolFunction(classContext, boolCastOpt.value(), s);
-
- if (smartPointerType == TypeSystem::SmartPointerType::Shared)
- writeSmartPointerRichCompareFunction(s, classContext);
-
- s << closeExternC;
-
- if (hasHashFunction(metaClass))
- writeHashFunction(s, classContext);
-
- // Write tp_traverse and tp_clear functions.
- writeTpTraverseFunction(s, metaClass);
- writeTpClearFunction(s, metaClass);
-
- writeClassDefinition(s, metaClass, classContext);
-
- s << '\n';
-
- writeConverterFunctions(s, metaClass, classContext);
- writeClassRegister(s, metaClass, classContext, signatureStream);
-
- // class inject-code native/end
- if (!typeEntry->codeSnips().isEmpty()) {
- writeClassCodeSnips(s, typeEntry->codeSnips(),
- TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode,
- classContext);
- s << '\n';
- }
-}
-
void CppGenerator::writeMethodWrapper(TextStream &s, TextStream &definitionStream,
TextStream &signatureStream,
const AbstractMetaFunctionCList &overloads,
@@ -997,7 +875,7 @@ void CppGenerator::writeConstructorNative(TextStream &s, const GeneratorContext
}
void CppGenerator::writeDestructorNative(TextStream &s,
- const GeneratorContext &classContext) const
+ const GeneratorContext &classContext)
{
s << classContext.wrapperName() << "::~"
<< classContext.wrapperName() << "()\n{\n" << indent;
@@ -1022,9 +900,10 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
// SbkType would return null when the type is a container.
auto typeEntry = func->type().typeEntry();
if (typeEntry->isContainer()) {
- const auto *cte = static_cast<const ContainerTypeEntry *>(typeEntry);
+ const auto cte = std::static_pointer_cast<const ContainerTypeEntry>(typeEntry);
switch (cte->containerKind()) {
case ContainerTypeEntry::ListContainer:
+ case ContainerTypeEntry::SpanContainer:
break;
case ContainerTypeEntry::SetContainer:
return uR"("set")"_s;
@@ -1051,8 +930,8 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
if (func->type().isPrimitive())
return u'"' + func->type().name() + u'"';
- return u"reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< "_s
- + typeEntry->qualifiedCppName() + u" >())->tp_name"_s;
+ return u"Shiboken::SbkType< "_s
+ + typeEntry->qualifiedCppName() + u" >()->tp_name"_s;
}
// When writing an overridden method of a wrapper class, write the part
@@ -1062,8 +941,8 @@ void CppGenerator::writeVirtualMethodCppCall(TextStream &s,
const QString &funcName,
const CodeSnipList &snips,
const AbstractMetaArgument *lastArg,
- const TypeEntry *retType,
- const QString &returnStatement) const
+ const TypeEntryCPtr &retType,
+ const QString &returnStatement, bool hasGil) const
{
if (!snips.isEmpty()) {
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning,
@@ -1071,12 +950,17 @@ void CppGenerator::writeVirtualMethodCppCall(TextStream &s,
}
if (func->isAbstract()) {
+ if (!hasGil)
+ s << "Shiboken::GilState gil;\n";
s << "Shiboken::Errors::setPureVirtualMethodError(\""
<< func->ownerClass()->name() << '.' << funcName << "\");\n"
<< returnStatement << '\n';
return;
}
+ if (hasGil)
+ s << "gil.release();\n";
+
if (retType)
s << "return ";
s << "this->::" << func->implementingClass()->qualifiedCppName() << "::";
@@ -1092,17 +976,24 @@ void CppGenerator::writeVirtualMethodCppCall(TextStream &s,
}
// Determine the return statement (void or a result value).
-QString CppGenerator::virtualMethodReturn(TextStream &s, const ApiExtractorResult &api,
- const AbstractMetaFunctionCPtr &func,
- const FunctionModificationList &functionModifications)
+
+CppGenerator::VirtualMethodReturn
+ CppGenerator::virtualMethodReturn(const ApiExtractorResult &api,
+ const AbstractMetaFunctionCPtr &func,
+ const FunctionModificationList &functionModifications)
{
- if (func->isVoid())
- return u"return;"_s;
+ VirtualMethodReturn result;
+ if (func->isVoid()) {
+ result.statement = "return;"_L1;
+ return result;
+ }
+
+ result.statement = "return "_L1;
const AbstractMetaType &returnType = func->type();
for (const FunctionModification &mod : functionModifications) {
for (const ArgumentModification &argMod : mod.argument_mods()) {
if (argMod.index() == 0 && !argMod.replacedDefaultExpression().isEmpty()) {
- static const QRegularExpression regex(QStringLiteral("%(\\d+)"));
+ static const QRegularExpression regex("%(\\d+)"_L1);
Q_ASSERT(regex.isValid());
QString expr = argMod.replacedDefaultExpression();
for (int offset = 0; ; ) {
@@ -1118,8 +1009,8 @@ QString CppGenerator::virtualMethodReturn(TextStream &s, const ApiExtractorResul
offset = match.capturedStart(1);
}
DefaultValue defaultReturnExpr(DefaultValue::Custom, expr);
- return u"return "_s + defaultReturnExpr.returnValue()
- + u';';
+ result.statement += defaultReturnExpr.returnValue() + u';';
+ return result;
}
}
}
@@ -1131,31 +1022,28 @@ QString CppGenerator::virtualMethodReturn(TextStream &s, const ApiExtractorResul
errorMsg = msgCouldNotFindMinimalConstructor(errorMsg,
func->type().cppSignature(),
errorMessage);
- qCWarning(lcShiboken).noquote().nospace() << errorMsg;
- s << "\n#error " << errorMsg << '\n';
- }
- if (returnType.referenceType() == LValueReference) {
- s << "static " << returnType.typeEntry()->qualifiedCppName()
- << " result;\n";
- return u"return result;"_s;
+ throw Exception(errorMsg);
}
- return u"return "_s + defaultReturnExpr->returnValue()
- + u';';
+
+ result.needsReference = returnType.referenceType() == LValueReference;
+ result.statement += (result.needsReference
+ ? virtualMethodStaticReturnVar : defaultReturnExpr->returnValue()) + u';';
+ return result;
}
// Create an argument for Py_BuildValue() when writing virtual methods.
// Return a pair of (argument, format-char).
-QPair<QString, QChar> CppGenerator::virtualMethodNativeArg(const AbstractMetaFunctionCPtr &func,
- const AbstractMetaArgument &arg)
+std::pair<QString, QChar> CppGenerator::virtualMethodNativeArg(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaArgument &arg)
{
if (func->hasConversionRule(TypeSystem::TargetLangCode, arg.argumentIndex() + 1))
return {arg.name() + CONV_RULE_OUT_VAR_SUFFIX, u'N'};
const auto &type = arg.type();
- auto *argTypeEntry = type.typeEntry();
+ auto argTypeEntry = type.typeEntry();
// Check for primitive types convertible by Py_BuildValue()
if (argTypeEntry->isPrimitive() && !type.isCString()) {
- const auto *pte = argTypeEntry->asPrimitive()->basicReferencedTypeEntry();
+ const auto pte = basicReferencedTypeEntry(argTypeEntry);
auto it = formatUnits().constFind(pte->name());
if (it != formatUnits().constEnd())
return {arg.name(), it.value()};
@@ -1167,10 +1055,41 @@ QPair<QString, QChar> CppGenerator::virtualMethodNativeArg(const AbstractMetaFun
return {ac.toString(), u'N'};
}
+static const char PYTHON_ARGS_ARRAY[] = "pyArgArray";
+
+void CppGenerator::writeVirtualMethodNativeVectorCallArgs(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaArgumentList &arguments,
+ const QList<int> &invalidateArgs)
+{
+ Q_ASSERT(!arguments.isEmpty());
+ s << "PyObject *" << PYTHON_ARGS_ARRAY <<'[' << arguments.size() << "] = {\n" << indent;
+ const qsizetype last = arguments.size() - 1;
+ for (qsizetype i = 0; i <= last; ++i) {
+ const AbstractMetaArgument &arg = arguments.at(i);
+ if (func->hasConversionRule(TypeSystem::TargetLangCode, arg.argumentIndex() + 1)) {
+ s << arg.name() + CONV_RULE_OUT_VAR_SUFFIX;
+ } else {
+ writeToPythonConversion(s, arg.type(), func->ownerClass(), arg.name());
+ }
+ if (i < last)
+ s << ',';
+ s << '\n';
+ }
+ s << outdent << "};\n";
+
+ if (!invalidateArgs.isEmpty())
+ s << '\n';
+ for (int index : invalidateArgs) {
+ s << "const bool invalidateArg" << index << " = Py_REFCNT(" << PYTHON_ARGS_ARRAY <<
+ '[' << index - 1 << "]) == 1;\n";
+ }
+}
+
void CppGenerator::writeVirtualMethodNativeArgs(TextStream &s,
const AbstractMetaFunctionCPtr &func,
const AbstractMetaArgumentList &arguments,
- const QList<int> &invalidateArgs) const
+ const QList<int> &invalidateArgs)
{
s << "Shiboken::AutoDecRef " << PYTHON_ARGS << '(';
if (arguments.isEmpty()) {
@@ -1189,22 +1108,61 @@ void CppGenerator::writeVirtualMethodNativeArgs(TextStream &s,
s << "Py_BuildValue(\"(" << format << ")\",\n"
<< indent << argConversions.join(u",\n"_s) << outdent << "\n));\n";
- for (int index : qAsConst(invalidateArgs)) {
- s << "bool invalidateArg" << index << " = PyTuple_GET_ITEM(" << PYTHON_ARGS
- << ", " << index - 1 << ")->ob_refcnt == 1;\n";
+ for (int index : std::as_const(invalidateArgs)) {
+ s << "bool invalidateArg" << index << " = Py_REFCNT(PyTuple_GET_ITEM(" << PYTHON_ARGS
+ << ", " << index - 1 << ")) == 1;\n";
}
}
-static bool isArgumentRemoved(const AbstractMetaArgument &a)
+static bool isArgumentNotRemoved(const AbstractMetaArgument &a)
+{
+ return !a.isModifiedRemoved();
+}
+
+// PyObject_Vectorcall(): since 3.9
+static const char vectorCallCondition[] =
+ "#if !defined(PYPY_VERSION) && !defined(Py_LIMITED_API)\n";
+
+// PyObject_CallNoArgs(): since 3.9, stable API since 3.10
+static const char noArgsCallCondition[] =
+ "#if !defined(PYPY_VERSION) && ((defined(Py_LIMITED_API) && Py_LIMITED_API >= 0x030A0000) || !defined(Py_LIMITED_API))\n";
+static const char inverseNoArgsCallCondition[] =
+ "#if defined(PYPY_VERSION) || (defined(Py_LIMITED_API) && Py_LIMITED_API < 0x030A0000)\n";
+
+static inline void writeVirtualMethodStaticReturnVar(TextStream &s, const AbstractMetaFunctionCPtr &func)
+{
+ s << "static " << func->type().typeEntry()->qualifiedCppName() << ' '
+ << virtualMethodStaticReturnVar << ";\n";
+}
+
+static void writeFuncNameVar(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ const QString &funcName)
{
- return a.isModifiedRemoved();
+ // PYSIDE-1019: Add info about properties
+ int propFlag = 0;
+ if (func->isPropertyReader())
+ propFlag |= 1;
+ if (func->isPropertyWriter())
+ propFlag |= 2;
+ if (propFlag && func->isStatic())
+ propFlag |= 4;
+ QString propStr;
+ if (propFlag != 90)
+ propStr = QString::number(propFlag) + u':';
+
+ if (propFlag != 0)
+ s << "// This method belongs to a property.\n";
+ s << "static const char *funcName = \"";
+ if (propFlag != 0)
+ s << propFlag << ':';
+ s << funcName << "\";\n";
}
void CppGenerator::writeVirtualMethodNative(TextStream &s,
const AbstractMetaFunctionCPtr &func,
int cacheIndex) const
{
- const TypeEntry *retType = func->type().typeEntry();
+ TypeEntryCPtr retType = func->type().typeEntry();
const QString funcName = func->isOperatorOverload()
? pythonOperatorFunctionName(func) : func->definitionNames().constFirst();
@@ -1213,12 +1171,16 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
Generator::OriginalTypeDescription)
<< "\n{\n" << indent;
- const QString returnStatement = virtualMethodReturn(s, api(), func,
- func->modifications());
+ const auto returnStatement = virtualMethodReturn(api(), func,
+ func->modifications());
- if (func->isAbstract() && func->isModifiedRemoved()) {
- qCWarning(lcShiboken, "%s", qPrintable(msgPureVirtualFunctionRemoved(func.data())));
- s << returnStatement << '\n' << outdent << "}\n\n";
+ if (returnStatement.needsReference)
+ writeVirtualMethodStaticReturnVar(s, func);
+
+ const bool isAbstract = func->isAbstract();
+ if (isAbstract && func->isModifiedRemoved()) {
+ qCWarning(lcShiboken, "%s", qPrintable(msgPureVirtualFunctionRemoved(func.get())));
+ s << returnStatement.statement << '\n' << outdent << "}\n\n";
return;
}
@@ -1243,48 +1205,45 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
<< R"(] << '\n';)" << '\n';
}
// PYSIDE-803: Build a boolean cache for unused overrides
- const bool multi_line = func->isVoid() || !snips.isEmpty() || func->isAbstract();
- s << "if (m_PyMethodCache[" << cacheIndex << "])" << (multi_line ? " {\n" : "\n");
- {
- Indentation indentation(s);
- writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
- returnStatement);
- }
+ const bool multi_line = func->isVoid() || !snips.isEmpty() || isAbstract;
+ s << "if (m_PyMethodCache[" << cacheIndex << "])" << (multi_line ? " {\n" : "\n")
+ << indent;
+ writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
+ returnStatement.statement, false);
+ s << outdent;
if (multi_line)
s << "}\n";
s << "Shiboken::GilState gil;\n";
// Get out of virtual method call if someone already threw an error.
- s << "if (PyErr_Occurred())\n" << indent
- << returnStatement << '\n' << outdent;
-
- // PYSIDE-1019: Add info about properties
- int propFlag = 0;
- if (func->isPropertyReader())
- propFlag |= 1;
- if (func->isPropertyWriter())
- propFlag |= 2;
- if (propFlag && func->isStatic())
- propFlag |= 4;
- QString propStr;
- if (propFlag)
- propStr = QString::number(propFlag) + u':';
+ s << "if (" << shibokenErrorsOccurred << ")\n" << indent
+ << returnStatement.statement << '\n' << outdent;
s << "static PyObject *nameCache[2] = {};\n";
- if (propFlag)
- s << "// This method belongs to a property.\n";
- s << "static const char *funcName = \"" << propStr << funcName << "\";\n"
- << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR
+ writeFuncNameVar(s, func, funcName);
+ s << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR
<< "(Shiboken::BindingManager::instance().getOverride(this, nameCache, funcName));\n"
- << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n"
- << indent << "gil.release();\n";
+ << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n" << indent;
if (useOverrideCaching(func->ownerClass()))
s << "m_PyMethodCache[" << cacheIndex << "] = true;\n";
writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
- returnStatement);
+ returnStatement.statement, true);
s << outdent << "}\n\n"; //WS
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionPyOverride,
+ TypeSystem::ShellCode, func, false, lastArg);
+ }
+
+ writeVirtualMethodPythonOverride(s, func, snips, returnStatement);
+}
+
+void CppGenerator::writeVirtualMethodPythonOverride(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const CodeSnipList &snips,
+ const VirtualMethodReturn &returnStatement) const
+{
writeConversionRule(s, func, TypeSystem::TargetLangCode, false);
bool invalidateReturn = false;
@@ -1305,9 +1264,34 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
std::sort(invalidateArgs.begin(), invalidateArgs.end());
auto arguments = func->arguments();
- auto removedEnd = std::remove_if(arguments.begin(), arguments.end(), isArgumentRemoved);
+ auto removedEnd = std::stable_partition(arguments.begin(), arguments.end(),
+ isArgumentNotRemoved);
+ if (func->isAbstract()) { // Base function is not called, indicate unused arguments.
+ for (auto it = removedEnd; it != arguments.end(); ++it)
+ s << sbkUnusedVariableCast(it->name());
+ }
arguments.erase(removedEnd, arguments.end());
+
+ // FIXME PYSIDE-7: new functions PyObject_Vectorcall() (since 3.9) and
+ // PyObject_CallNoArgs() (since 3.9, stable API since 3.10) might have
+ // become part of the stable API?
+
+ // Code snips might expect the args tuple, don't generate new code
+ const bool generateNewCall = snips.isEmpty();
+ const qsizetype argCount = arguments.size();
+ const char *newCallCondition = argCount == 0 ? noArgsCallCondition : vectorCallCondition;
+ if (generateNewCall) {
+ if (argCount > 0) {
+ s << newCallCondition;
+ writeVirtualMethodNativeVectorCallArgs(s, func, arguments, invalidateArgs);
+ s << "#else\n";
+ } else {
+ s << inverseNoArgsCallCondition;
+ }
+ }
writeVirtualMethodNativeArgs(s, func, arguments, invalidateArgs);
+ if (generateNewCall)
+ s << "#endif\n";
s << '\n';
if (!snips.isEmpty()) {
@@ -1323,23 +1307,42 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
qsizetype returnIndirections = 0;
if (!func->injectedCodeCallsPythonOverride()) {
+ if (generateNewCall) {
+ s << newCallCondition << "Shiboken::AutoDecRef " << PYTHON_RETURN_VAR << '(';
+ if (argCount > 0) {
+ s << "PyObject_Vectorcall(" << PYTHON_OVERRIDE_VAR << ", "
+ << PYTHON_ARGS_ARRAY << ", " << argCount << ", nullptr));\n";
+ for (int argIndex : std::as_const(invalidateArgs)) {
+ s << "if (invalidateArg" << argIndex << ")\n" << indent
+ << "Shiboken::Object::invalidate(" << PYTHON_ARGS_ARRAY
+ << '[' << (argIndex - 1) << "]);\n" << outdent;
+ }
+ for (qsizetype i = 0, size = arguments.size(); i < size; ++i)
+ s << "Py_DECREF(" << PYTHON_ARGS_ARRAY << '[' << i << "]);\n";
+ } else {
+ s << "PyObject_CallNoArgs(" << PYTHON_OVERRIDE_VAR << "));\n";
+ }
+ s << "#else\n";
+ }
s << "Shiboken::AutoDecRef " << PYTHON_RETURN_VAR << "(PyObject_Call("
<< PYTHON_OVERRIDE_VAR << ", " << PYTHON_ARGS << ", nullptr));\n";
- for (int argIndex : qAsConst(invalidateArgs)) {
+ for (int argIndex : std::as_const(invalidateArgs)) {
s << "if (invalidateArg" << argIndex << ")\n" << indent
<< "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS
<< ", " << (argIndex - 1) << "));\n" << outdent;
}
+ if (generateNewCall)
+ s << "#endif\n";
s << "if (" << PYTHON_RETURN_VAR << ".isNull()) {\n" << indent
<< "// An error happened in python code!\n"
- << "PyErr_Print();\n"
- << returnStatement << "\n" << outdent
+ << "Shiboken::Errors::storeErrorOrPrint();\n"
+ << returnStatement.statement << "\n" << outdent
<< "}\n";
if (invalidateReturn) {
- s << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;\n"
+ s << "bool invalidateArg0 = Py_REFCNT(" << PYTHON_RETURN_VAR << ") == 1;\n"
<< "if (invalidateArg0)\n" << indent
<< "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR
<< ".object());\n" << outdent;
@@ -1347,7 +1350,7 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
if (!func->isVoid()) {
- if (func->modifiedTypeName() != cPyObjectT()) {
+ if (func->modifiedTypeName() != cPyObjectT) {
s << "// Check return type\n";
@@ -1359,10 +1362,10 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
<< PYTHON_RETURN_VAR << ");\n" << outdent
<< "if (!" << PYTHON_TO_CPP_VAR << ") {\n" << indent
<< "Shiboken::Warnings::warnInvalidReturnValue(\""
- << func->ownerClass()->name() << "\", \"" << funcName << "\", "
+ << func->ownerClass()->name() << "\", funcName, "
<< getVirtualFunctionReturnTypeName(func) << ", "
<< "Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"
- << returnStatement << '\n' << outdent
+ << returnStatement.statement << '\n' << outdent
<< "}\n";
} else {
@@ -1381,10 +1384,10 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
s << " && " << PYTHON_RETURN_VAR << " != Py_None";
s << ") {\n" << indent
<< "Shiboken::Warnings::warnInvalidReturnValue(\""
- << func->ownerClass()->name() << "\", \"" << funcName << "\", "
+ << func->ownerClass()->name() << "\", funcName, "
<< getVirtualFunctionReturnTypeName(func) << ", "
<< "Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n"
- << returnStatement << '\n' << outdent
+ << returnStatement.statement << '\n' << outdent
<< "}\n";
}
@@ -1421,13 +1424,14 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
if (!func->isVoid()) {
s << "return ";
+ TypeEntryCPtr retType = func->type().typeEntry();
if (avoidProtectedHack() && retType->isEnum()) {
auto metaEnum = api().findAbstractMetaEnum(retType);
bool isProtectedEnum = metaEnum.has_value() && metaEnum->isProtected();
if (isProtectedEnum) {
QString typeCast;
if (metaEnum->enclosingClass())
- typeCast += u"::"_s + metaEnum->enclosingClass()->qualifiedCppName();
+ typeCast += getFullTypeName(metaEnum->enclosingClass());
typeCast += u"::"_s + metaEnum->name();
s << '(' << typeCast << ')';
}
@@ -1441,6 +1445,28 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
s << outdent << "}\n\n";
}
+void CppGenerator::writeUserAddedPythonOverride(TextStream &s,
+ const AbstractMetaFunctionCPtr &func) const
+{
+ TypeEntryCPtr retType = func->type().typeEntry();
+ const QString funcName = func->isOperatorOverload()
+ ? pythonOperatorFunctionName(func) : func->definitionNames().constFirst();
+
+ const CodeSnipList snips = func->hasInjectedCode()
+ ? func->injectedCodeSnips() : CodeSnipList();
+
+ QString prefix = wrapperName(func->ownerClass()) + u"::"_s;
+ s << '\n' << functionSignature(func, prefix, QString(), Generator::SkipDefaultValues |
+ Generator::OriginalTypeDescription)
+ << "\n{\n" << indent << sbkUnusedVariableCast("gil");
+
+ writeFuncNameVar(s, func, funcName);
+
+ const auto returnStatement = virtualMethodReturn(api(), func,
+ func->modifications());
+ writeVirtualMethodPythonOverride(s, func, snips, returnStatement);
+}
+
void CppGenerator::writeMetaObjectMethod(TextStream &s,
const GeneratorContext &classContext) const
{
@@ -1448,7 +1474,7 @@ void CppGenerator::writeMetaObjectMethod(TextStream &s,
const QString wrapperClassName = classContext.wrapperName();
const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName();
s << "const QMetaObject *" << wrapperClassName << "::metaObject() const\n{\n";
- s << indent << "if (QObject::d_ptr->metaObject)\n"
+ s << indent << "if (QObject::d_ptr->metaObject != nullptr)\n"
<< indent << "return QObject::d_ptr->dynamicMetaObject();\n" << outdent
<< "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n"
<< "if (pySelf == nullptr)\n"
@@ -1491,42 +1517,65 @@ void CppGenerator::writeMetaCast(TextStream &s,
const QString wrapperClassName = classContext.wrapperName();
const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName();
s << "void *" << wrapperClassName << "::qt_metacast(const char *_clname)\n{\n"
- << indent << "if (!_clname)\n" << indent << "return {};\n" << outdent
+ << indent << "if (_clname == nullptr)\n" << indent << "return {};\n" << outdent
<< "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n"
- << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))\n"
+ << "if (pySelf != nullptr && PySide::inherits(Py_TYPE(pySelf), _clname))\n"
<< indent << "return static_cast<void *>(const_cast< "
<< wrapperClassName << " *>(this));\n" << outdent
<< "return " << qualifiedCppName << "::qt_metacast(_clname);\n"
<< outdent << "}\n\n";
}
-void CppGenerator::writeEnumConverterFunctions(TextStream &s, const AbstractMetaEnum &metaEnum) const
+static void generateDeprecatedValueWarnings(TextStream &c,
+ const AbstractMetaEnum &metaEnum,
+ bool useSurrogateName)
{
- if (metaEnum.isPrivate() || metaEnum.isAnonymous())
- return;
- writeEnumConverterFunctions(s, metaEnum.typeEntry());
+ EnumTypeEntryCPtr enumType = metaEnum.typeEntry();
+ const QString prefix = enumType->qualifiedCppName() + u"::"_s;
+ c << "switch (value) {\n";
+ const auto &deprecatedValues = metaEnum.deprecatedValues();
+ for (const auto &v : deprecatedValues) {
+ c << "case ";
+ if (useSurrogateName)
+ c << v.value().toString(); // Protected, use int representation
+ else
+ c << prefix << v.name();
+ c << ":\n" << indent
+ << "Shiboken::Warnings::warnDeprecatedEnumValue(\"" << enumType->name()
+ << "\", \"" << v.name() << "\");\nbreak;\n" << outdent;
+ }
+ if (deprecatedValues.size() < metaEnum.values().size())
+ c << "default:\n" << indent << "break;\n" << outdent;
+ c << "}\n";
}
-void CppGenerator::writeEnumConverterFunctions(TextStream &s, const TypeEntry *enumType) const
+void CppGenerator::writeEnumConverterFunctions(TextStream &s, const AbstractMetaEnum &metaEnum) const
{
- if (!enumType)
+ if (metaEnum.isPrivate() || metaEnum.isAnonymous())
return;
+ EnumTypeEntryCPtr enumType = metaEnum.typeEntry();
+ Q_ASSERT(enumType);
QString typeName = fixedCppTypeName(enumType);
QString enumPythonType = cpythonTypeNameExt(enumType);
- QString cppTypeName = getFullTypeName(enumType).trimmed();
- if (avoidProtectedHack()) {
- auto metaEnum = api().findAbstractMetaEnum(enumType);
- if (metaEnum.has_value() && metaEnum->isProtected())
- cppTypeName = protectedEnumSurrogateName(metaEnum.value());
- }
+ const bool useSurrogateName = avoidProtectedHack() && metaEnum.isProtected();
+ QString cppTypeName = useSurrogateName
+ ? protectedEnumSurrogateName(metaEnum) : getFullTypeName(enumType).trimmed();
+
StringStream c(TextStream::Language::Cpp);
- c << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << " ";
- if (enumType->isFlags())
- c << cppTypeName << "(QFlag(int(PySide::QFlags::getValue(reinterpret_cast<PySideQFlagsObject *>(pyIn)))))";
- else
- c << "static_cast<" << cppTypeName << ">(Shiboken::Enum::getValue(pyIn))";
- c << ";\n";
+ if (metaEnum.isDeprecated())
+ c << "Shiboken::Warnings::warnDeprecatedEnum(\"" << enumType->name() << "\");\n";
+
+ c << "const auto value = static_cast<" << cppTypeName
+ << ">(Shiboken::Enum::getValue(pyIn));\n";
+
+ // Warn about deprecated values unless it is protected+scoped (inaccessible values)
+ const bool valuesAcccessible = !useSurrogateName || metaEnum.enumKind() != EnumClass;
+ if (valuesAcccessible && metaEnum.hasDeprecatedValues())
+ generateDeprecatedValueWarnings(c, metaEnum, useSurrogateName);
+
+ c << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) = value;\n";
+
+ ConfigurableScope configScope(s, enumType);
writePythonToCppFunction(s, c.toString(), typeName, typeName);
QString pyTypeCheck = u"PyObject_TypeCheck(pyIn, "_s + enumPythonType + u')';
@@ -1535,65 +1584,50 @@ void CppGenerator::writeEnumConverterFunctions(TextStream &s, const TypeEntry *e
c.clear();
c << "const int castCppIn = int(*reinterpret_cast<const "
- << cppTypeName << " *>(cppIn));\n" << "return ";
- if (enumType->isFlags()) {
- c << "reinterpret_cast<PyObject *>(PySide::QFlags::newObject(castCppIn, "
- << enumPythonType << "))";
- } else {
- c << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn)";
- }
- c << ";\n";
+ << cppTypeName << " *>(cppIn));\n" << "return "
+ << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn);\n";
writeCppToPythonFunction(s, c.toString(), typeName, typeName);
s << '\n';
+}
- if (enumType->isFlags())
- return;
+static void writePointerToPythonConverter(TextStream &c,
+ const AbstractMetaClassCPtr &metaClass,
+ const QString &typeName,
+ const QString &cpythonType)
+{
+ c << "auto *pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppIn));\n"
+ << "if (pyOut) {\n" << indent
+ << "Py_INCREF(pyOut);\nreturn pyOut;\n" << outdent
+ << "}\n";
- auto flags = reinterpret_cast<const EnumTypeEntry *>(enumType)->flags();
- if (!flags)
+ const QString nameFunc = metaClass->typeEntry()->polymorphicNameFunction();
+ if (nameFunc.isEmpty() && !metaClass->hasVirtualDestructor()) {
+ c << "return Shiboken::Object::newObjectWithHeuristics("
+ << cpythonType << ", const_cast<void *>(cppIn), false);\n";
return;
+ }
- // QFlags part.
-
- writeEnumConverterFunctions(s, flags);
-
- c.clear();
- cppTypeName = getFullTypeName(flags).trimmed();
- c << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << " " << cppTypeName
- << "(QFlag(int(Shiboken::Enum::getValue(pyIn))));\n";
-
- QString flagsTypeName = fixedCppTypeName(flags);
- writePythonToCppFunction(s, c.toString(), typeName, flagsTypeName);
- writeIsPythonConvertibleToCppFunction(s, typeName, flagsTypeName, pyTypeCheck);
+ c << "auto *tCppIn = reinterpret_cast<const " << typeName << R"( *>(cppIn);
+const char *typeName = )";
+ if (nameFunc.isEmpty())
+ c << "typeid(*tCppIn).name();\n";
+ else
+ c << nameFunc << "(tCppIn);\n";
+ c << "return Shiboken::Object::newObjectForPointer("
+ << cpythonType << ", const_cast<void *>(cppIn), false, typeName);\n";
+}
- c.clear();
- c << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));\n"
- << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << " " << cppTypeName
- << "(QFlag(int(PyLong_AsLong(pyLong.object()))));\n";
- // PYSIDE-898: Include an additional condition to detect if the type of the
- // enum corresponds to the object that is being evaluated.
- // Using only `PyNumber_Check(...)` is too permissive,
- // then we would have been unable to detect the difference between
- // a PolarOrientation and Qt::AlignmentFlag, which was the main
- // issue of the bug.
- const QString numberCondition = QStringLiteral("PyNumber_Check(pyIn) && ") + pyTypeCheck;
- writePythonToCppFunction(s, c.toString(), u"number"_s, flagsTypeName);
- writeIsPythonConvertibleToCppFunction(s, u"number"_s, flagsTypeName, numberCondition);
-}
-
-void CppGenerator::writeConverterFunctions(TextStream &s, const AbstractMetaClass *metaClass,
+void CppGenerator::writeConverterFunctions(TextStream &s, const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext) const
{
s << "// Type conversion functions.\n\n";
AbstractMetaEnumList classEnums = metaClass->enums();
- auto *typeEntry = metaClass->typeEntry();
+ auto typeEntry = metaClass->typeEntry();
metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
if (!classEnums.isEmpty())
s << "// Python to C++ enum conversion.\n";
- for (const AbstractMetaEnum &metaEnum : qAsConst(classEnums))
+ for (const AbstractMetaEnum &metaEnum : std::as_const(classEnums))
writeEnumConverterFunctions(s, metaEnum);
if (metaClass->isNamespace())
@@ -1624,37 +1658,11 @@ void CppGenerator::writeConverterFunctions(TextStream &s, const AbstractMetaClas
// C++ pointer to a Python wrapper, keeping identity.
s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity).\n";
c.clear();
- if (usePySideExtensions() && metaClass->isQObject()) {
+ if (usePySideExtensions() && isQObject(metaClass)) {
c << "return PySide::getWrapperForQObject(reinterpret_cast<"
<< typeName << " *>(const_cast<void *>(cppIn)), " << cpythonType << ");\n";
} else {
- c << "auto pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppIn));\n"
- << "if (pyOut) {\n";
- {
- Indentation indent(c);
- c << "Py_INCREF(pyOut);\nreturn pyOut;\n";
- }
- c << "}\n"
- << "bool changedTypeName = false;\n"
- << "auto tCppIn = reinterpret_cast<const " << typeName << R"( *>(cppIn);
-const char *typeName = )";
-
- const QString nameFunc = metaClass->typeEntry()->polymorphicNameFunction();
- if (nameFunc.isEmpty())
- c << "typeid(*tCppIn).name();\n";
- else
- c << nameFunc << "(tCppIn);\n";
- c << R"(auto sbkType = Shiboken::ObjectType::typeForTypeName(typeName);
-if (sbkType && Shiboken::ObjectType::hasSpecialCastFunction(sbkType)) {
- typeName = typeNameOf(tCppIn);
- changedTypeName = true;
-}
-)"
- << "PyObject *result = Shiboken::Object::newObject(" << cpythonType
- << R"(, const_cast<void *>(cppIn), false, /* exactType */ changedTypeName, typeName);
-if (changedTypeName)
- delete [] typeName;
-return result;)";
+ writePointerToPythonConverter(c, metaClass, typeName, cpythonType);
}
std::swap(targetTypeName, sourceTypeName);
writeCppToPythonFunction(s, c.toString(), sourceTypeName, targetTypeName);
@@ -1683,7 +1691,7 @@ return result;)";
c << "auto *source = reinterpret_cast<const " << typeName << " *>(cppIn);\n";
}
c << "return Shiboken::Object::newObject(" << cpythonType
- << ", new ::" << classContext.effectiveClassName() << '('
+ << ", new " << globalScopePrefix(classContext) << classContext.effectiveClassName() << '('
<< (isUniquePointer ? "std::move(*source)" : "*source")
<< "), true, true);";
writeCppToPythonFunction(s, c.toString(), sourceTypeName, targetTypeName);
@@ -1693,7 +1701,7 @@ return result;)";
s << "// Python to C++ copy conversion.\n";
sourceTypeName = metaClass->name();
- targetTypeName = sourceTypeName + QStringLiteral("_COPY");
+ targetTypeName = sourceTypeName + "_COPY"_L1;
c.clear();
QString pyInVariable = u"pyIn"_s;
@@ -1702,7 +1710,7 @@ return result;)";
c << '*' << outPtr << " = *"
<< cpythonWrapperCPtr(typeEntry, pyInVariable) << ';';
} else {
- auto *ste = static_cast<const SmartPointerTypeEntry *>(typeEntry);
+ auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(typeEntry);
const QString resetMethod = ste->resetMethod();
c << "auto *ptr = " << outPtr << ";\n";
c << "if (" << pyInVariable << " == Py_None)\n" << indent;
@@ -1732,7 +1740,7 @@ return result;)";
s << "// Implicit conversions.\n";
AbstractMetaType targetType = AbstractMetaType::fromAbstractMetaClass(metaClass);
- for (const auto &conv : qAsConst(implicitConvs)) {
+ for (const auto &conv : std::as_const(implicitConvs)) {
if (conv->isModifiedRemoved())
continue;
@@ -1740,7 +1748,7 @@ return result;)";
QString toCppConv;
QString toCppPreConv;
if (conv->isConversionOperator()) {
- const AbstractMetaClass *sourceClass = conv->ownerClass();
+ const auto sourceClass = conv->ownerClass();
typeCheck = u"PyObject_TypeCheck(pyIn, "_s
+ cpythonTypeNameExt(sourceClass->typeEntry()) + u')';
toCppConv = u'*' + cpythonWrapperCPtr(sourceClass->typeEntry(),
@@ -1774,14 +1782,14 @@ return result;)";
StringStream pc(TextStream::Language::Cpp);
pc << getFullTypeNameWithoutModifiers(sourceType) << " cppIn"
<< minimalConstructorExpression(api(), sourceType) << ";\n";
- writeToCppConversion(pc, sourceType, nullptr, pyInVariable,
+ writeToCppConversion(pc, sourceType, pyInVariable,
u"cppIn"_s);
pc << ';';
toCppPreConv = pc.toString();
toCppConv.append(u"cppIn"_s);
} else if (!sourceType.isWrapperType()) {
StringStream tcc(TextStream::Language::Cpp);
- writeToCppConversion(tcc, sourceType, metaClass, pyInVariable,
+ writeToCppConversion(tcc, sourceType, pyInVariable,
u"/*BOZO-1061*/"_s);
toCppConv = tcc.toString();
}
@@ -1792,54 +1800,53 @@ return result;)";
writePythonToCppConversionFunctions(s, sourceType, targetType, typeCheck, toCppConv, toCppPreConv);
}
- writeCustomConverterFunctions(s, typeEntry->customConversion());
+ if (typeEntry->isValue()) {
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry);
+ writeCustomConverterFunctions(s, vte->customConversion());
+ }
}
void CppGenerator::writeCustomConverterFunctions(TextStream &s,
- const CustomConversion *customConversion) const
+ const CustomConversionPtr &customConversion) const
{
if (!customConversion)
return;
- const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
+ const TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
if (toCppConversions.isEmpty())
return;
- s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'.\n";
- for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions)
- writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType());
+ auto ownerType = customConversion->ownerType();
+ s << "// Python to C++ conversions for type '" << ownerType->qualifiedCppName() << "'.\n";
+ for (const auto &toNative : toCppConversions)
+ writePythonToCppConversionFunctions(s, toNative, ownerType);
s << '\n';
}
-void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass *metaClass,
+void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext) const
{
- const auto *typeEntry = metaClass->typeEntry();
+ const auto typeEntry = metaClass->typeEntry();
if (typeEntry->isNamespace())
return;
s << "// Register Converter\n"
- << "SbkConverter *converter = Shiboken::Conversions::createConverter(pyType,\n";
- {
- Indentation indent(s);
- QString sourceTypeName = metaClass->name();
- QString targetTypeName = sourceTypeName + u"_PTR"_s;
- s << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << '\n'
- << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << '\n';
- std::swap(targetTypeName, sourceTypeName);
+ << "SbkConverter *converter = Shiboken::Conversions::createConverter(pyType,\n"
+ << indent;
+ QString sourceTypeName = metaClass->name();
+ QString targetTypeName = sourceTypeName + u"_PTR"_s;
+ s << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << '\n'
+ << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << '\n';
+ std::swap(targetTypeName, sourceTypeName);
+ s << cppToPythonFunctionName(sourceTypeName, targetTypeName);
+ if (typeEntry->isValue() || typeEntry->isSmartPointer()) {
+ s << ',' << '\n';
+ sourceTypeName = metaClass->name() + u"_COPY"_s;
s << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- if (typeEntry->isValue() || typeEntry->isSmartPointer()) {
- s << ',' << '\n';
- sourceTypeName = metaClass->name() + u"_COPY"_s;
- s << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- }
}
- s << ");\n";
-
- s << '\n';
+ s << outdent << ");\n\n";
auto writeConversions = [&s](const QString &signature)
{
- s << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");\n"
- << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");\n"
- << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");\n";
+ s << registerConverterName(signature) << registerConverterName(signature + u'*')
+ << registerConverterName(signature + u'&');
};
auto writeConversionsForType = [writeConversions](const QString &fullTypeName)
@@ -1864,14 +1871,14 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
Qt::SkipEmptyParts);
while (!lst.isEmpty()) {
QString signature = lst.join(u"::"_s);
- writeConversions(smartPointerName + u'<' + signature + u" >"_s);
+ writeConversions(smartPointerName + u'<' + signature + u'>');
lst.removeFirst();
}
writeConversionsForType(smartPointerType);
}
- s << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
+ s << "Shiboken::Conversions::registerConverterName(converter, typeid(" << m_gsp;
QString qualifiedCppNameInvocation;
if (!classContext.forSmartPointer())
qualifiedCppNameInvocation = metaClass->qualifiedCppName();
@@ -1881,19 +1888,17 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
s << qualifiedCppNameInvocation << ").name());\n";
if (classContext.useWrapper()) {
- s << "Shiboken::Conversions::registerConverterName(converter, typeid(::"
+ s << "Shiboken::Conversions::registerConverterName(converter, typeid("
<< classContext.wrapperName() << ").name());\n";
}
- s << '\n';
-
if (!typeEntry->isValue() && !typeEntry->isSmartPointer())
return;
// Python to C++ copy (value, not pointer neither reference) conversion.
- s << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter.\n";
- QString sourceTypeName = metaClass->name();
- QString targetTypeName = sourceTypeName + u"_COPY"_s;
+ s << "\n// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter.\n";
+ sourceTypeName = metaClass->name();
+ targetTypeName = sourceTypeName + u"_COPY"_s;
QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
@@ -1907,7 +1912,7 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
s << "// Add implicit conversions to type converter.\n";
AbstractMetaType targetType = AbstractMetaType::fromAbstractMetaClass(metaClass);
- for (const auto &conv : qAsConst(implicitConvs)) {
+ for (const auto &conv : std::as_const(implicitConvs)) {
if (conv->isModifiedRemoved())
continue;
AbstractMetaType sourceType;
@@ -1925,19 +1930,24 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
}
- writeCustomConverterRegister(s, typeEntry->customConversion(), u"converter"_s);
+ if (typeEntry->isValue()) {
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(typeEntry);
+ writeCustomConverterRegister(s, vte->customConversion(), u"converter"_s);
+ }
}
-void CppGenerator::writeCustomConverterRegister(TextStream &s, const CustomConversion *customConversion,
+void CppGenerator::writeCustomConverterRegister(TextStream &s,
+ const CustomConversionPtr &customConversion,
const QString &converterVar)
{
if (!customConversion)
return;
- const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
+ const TargetToNativeConversions &toCppConversions =
+ customConversion->targetToNativeConversions();
if (toCppConversions.isEmpty())
return;
s << "// Add user defined implicit conversions to type converter.\n";
- for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) {
+ for (const auto &toNative : toCppConversions) {
QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType());
QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType());
writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
@@ -1951,46 +1961,7 @@ void CppGenerator::writeContainerConverterFunctions(TextStream &s,
writePythonToCppConversionFunctions(s, containerType);
}
-// Helpers to collect all smart pointer pointee base classes
-static AbstractMetaClassCList findSmartPointeeBaseClasses(const ApiExtractorResult &api,
- const AbstractMetaType &smartPointerType)
-{
- AbstractMetaClassCList result;
- auto *instantiationsTe = smartPointerType.instantiations().at(0).typeEntry();
- auto targetClass = AbstractMetaClass::findClass(api.classes(), instantiationsTe);
- if (targetClass != nullptr)
- result = targetClass->allTypeSystemAncestors();
- return result;
-}
-
-void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
- const AbstractMetaType &smartPointerType) const
-{
- const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
- if (baseClasses.isEmpty())
- return;
-
- auto *smartPointerTypeEntry =
- static_cast<const SmartPointerTypeEntry *>(smartPointerType.typeEntry());
-
- // TODO: Missing conversion to smart pointer pointer type:
-
- s << "// Register smartpointer conversion for all derived classes\n";
- for (auto *base : baseClasses) {
- auto *baseTe = base->typeEntry();
- if (smartPointerTypeEntry->matchesInstantiation(baseTe)) {
- if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
- const auto smartTargetType = opt.value();
- s << "// SmartPointer derived class: "
- << smartTargetType.cppSignature() << "\n";
- writePythonToCppConversionFunctions(s, smartPointerType,
- smartTargetType, {}, {}, {});
- }
- }
- }
-}
-
-bool CppGenerator::needsArgumentErrorHandling(const OverloadData &overloadData) const
+bool CppGenerator::needsArgumentErrorHandling(const OverloadData &overloadData)
{
if (overloadData.maxArgs() > 0)
return true;
@@ -1999,15 +1970,16 @@ bool CppGenerator::needsArgumentErrorHandling(const OverloadData &overloadData)
return false;
auto rfunc = overloadData.referenceFunction();
return rfunc->functionType() == AbstractMetaFunction::ConstructorFunction
- && rfunc->ownerClass()->isQObject();
+ && isQObject(rfunc->ownerClass());
}
-void CppGenerator::writeMethodWrapperPreamble(TextStream &s,const OverloadData &overloadData,
+void CppGenerator::writeMethodWrapperPreamble(TextStream &s,
+ const OverloadData &overloadData,
const GeneratorContext &context,
- ErrorReturn errorReturn) const
+ ErrorReturn errorReturn)
{
const auto rfunc = overloadData.referenceFunction();
- const AbstractMetaClass *ownerClass = rfunc->targetLangOwner();
+ const auto ownerClass = rfunc->targetLangOwner();
Q_ASSERT(ownerClass == context.metaClass());
int minArgs = overloadData.minArgs();
int maxArgs = overloadData.maxArgs();
@@ -2017,7 +1989,9 @@ void CppGenerator::writeMethodWrapperPreamble(TextStream &s,const OverloadData &
if (rfunc->isConstructor()) {
// Check if the right constructor was called.
if (!ownerClass->hasPrivateDestructor()) {
- s << "if (Shiboken::Object::isUserType(self) && !Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType< ::";
+ s << "if (Shiboken::Object::isUserType(self) && "
+ << "!Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType< "
+ << m_gsp;
QString qualifiedCppName;
if (!context.forSmartPointer())
qualifiedCppName = ownerClass->qualifiedCppName();
@@ -2027,7 +2001,7 @@ void CppGenerator::writeMethodWrapperPreamble(TextStream &s,const OverloadData &
s << qualifiedCppName << " >()))\n" << indent << errorReturn << outdent << '\n';
}
// Declare pointer for the underlying C++ object.
- s << "::" << context.effectiveClassName() << " *cptr{};\n";
+ s << globalScopePrefix(context) << context.effectiveClassName() << " *cptr{};\n";
initPythonArguments = maxArgs > 0;
@@ -2047,18 +2021,24 @@ void CppGenerator::writeMethodWrapperPreamble(TextStream &s,const OverloadData &
initPythonArguments = minArgs != maxArgs || maxArgs > 1;
}
- if (needsArgumentErrorHandling(overloadData)) {
- s << R"(Shiboken::AutoDecRef errInfo{};
-static const char fullName[] = ")" << fullPythonFunctionName(rfunc, true)
- << "\";\nSBK_UNUSED(fullName)\n";
- }
+ if (needsArgumentErrorHandling(overloadData))
+ s << "Shiboken::AutoDecRef errInfo{};\n";
+
+ s << "static const char fullName[] = \"" << fullPythonFunctionName(rfunc, true)
+ << "\";\nSBK_UNUSED(fullName)\n"
+ << "Shiboken::PythonContextMarker pcm;\n";
+ // PYSIDE-2335: Mark blocking calls like `exec` or `run` as such.
+ bool isBlockingFunction = rfunc->name() == u"exec"_s || rfunc->name() == u"exec_"_s
+ || rfunc->name() == u"run"_s;
+ if (isBlockingFunction)
+ s << "pcm.setBlocking();\n";
+
if (maxArgs > 0) {
s << "int overloadId = -1;\n"
<< PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR;
if (overloadData.pythonFunctionWrapperUsesListOfArguments())
s << '[' << maxArgs << ']';
- s << ";\n";
- writeUnusedVariableCast(s, PYTHON_TO_CPP_VAR);
+ s << ";\n" << sbkUnusedVariableCast(PYTHON_TO_CPP_VAR);
}
if (initPythonArguments) {
@@ -2078,17 +2058,20 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
const ErrorReturn errorReturn = ErrorReturn::MinusOne;
const auto rfunc = overloadData.referenceFunction();
- const AbstractMetaClass *metaClass = rfunc->ownerClass();
+ const auto metaClass = rfunc->ownerClass();
s << "static int\n";
s << cpythonFunctionName(rfunc)
<< "(PyObject *self, PyObject *args, PyObject *kwds)\n{\n" << indent;
+ if (overloadData.maxArgs() == 0 || metaClass->isAbstract())
+ s << sbkUnusedVariableCast("args");
+ s << sbkUnusedVariableCast("kwds");
- const bool needsMetaObject = usePySideExtensions() && metaClass->isQObject();
+ const bool needsMetaObject = usePySideExtensions() && isQObject(metaClass);
if (needsMetaObject)
s << "const QMetaObject *metaObject;\n";
- s << "SbkObject *sbkSelf = reinterpret_cast<SbkObject *>(self);\n";
+ s << "auto *sbkSelf = reinterpret_cast<SbkObject *>(self);\n";
if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) {
s << "PyTypeObject *type = self->ob_type;\n"
@@ -2099,11 +2082,11 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
if (metaClass->isAbstract()) {
// C++ Wrapper disabled: Abstract C++ class cannot be instantiated.
if (metaClass->typeEntry()->typeFlags().testFlag(ComplexTypeEntry::DisableWrapper)) {
- writeUnusedVariableCast(s, QStringLiteral("sbkSelf"));
- writeUnusedVariableCast(s, QStringLiteral("type"));
- writeUnusedVariableCast(s, QStringLiteral("myType"));
+ s << sbkUnusedVariableCast("sbkSelf")
+ << sbkUnusedVariableCast("type")
+ << sbkUnusedVariableCast("myType");
if (needsMetaObject)
- writeUnusedVariableCast(s, QStringLiteral("metaObject"));
+ s << sbkUnusedVariableCast("metaObject");
s << "Shiboken::Errors::setInstantiateAbstractClassDisabledWrapper(\""
<< metaClass->qualifiedCppName() << "\");\n" << errorReturn << outdent
<< "}\n\n";
@@ -2135,19 +2118,29 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
s << '\n';
if (overloadData.maxArgs() > 0)
- writeOverloadedFunctionDecisor(s, overloadData);
+ writeOverloadedFunctionDecisor(s, overloadData, errorReturn);
+
+ // Handles Python Multiple Inheritance
+ QString pre = needsMetaObject ? u"bool usesPyMI = "_s : u""_s;
+ s << "\n// PyMI support\n"
+ << pre << "Shiboken::callInheritedInit(self, args, kwds, fullName);\n"
+ << "if (" << shibokenErrorsOccurred << ")\n"
+ << indent << errorReturn << outdent << "\n";
writeFunctionCalls(s, overloadData, classContext, errorReturn);
s << '\n';
const QString typeName = classContext.forSmartPointer()
? classContext.preciseType().cppSignature() : metaClass->qualifiedCppName();
- s << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::"
- << typeName << " >(), cptr)) {\n"
+ s << "if (" << shibokenErrorsOccurred
+ << " || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< "
+ << globalScopePrefix(classContext) << typeName << " >(), cptr)) {\n"
<< indent << "delete cptr;\n" << errorReturn << outdent
<< "}\n";
if (overloadData.maxArgs() > 0)
- s << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;\n\n";
+ s << "if (cptr == nullptr)\n" << indent
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n\n"
+ << outdent;
s << "Shiboken::Object::setValidCpp(sbkSelf, true);\n";
// If the created C++ object has a C++ wrapper the ownership is assigned to Python
@@ -2158,13 +2151,10 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
s << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);\n";
// Need to check if a wrapper for same pointer is already registered
// Caused by bug PYSIDE-217, where deleted objects' wrappers are not released
- s << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {\n";
- {
- Indentation indent(s);
- s << "Shiboken::BindingManager::instance().releaseWrapper("
- "Shiboken::BindingManager::instance().retrieveWrapper(cptr));\n";
- }
- s << "}\nShiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);\n";
+ s << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {\n" << indent
+ << "Shiboken::BindingManager::instance().releaseWrapper("
+ "Shiboken::BindingManager::instance().retrieveWrapper(cptr));\n" << outdent
+ << "}\nShiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);\n";
// Create metaObject and register signal/slot
if (needsMetaObject) {
@@ -2172,8 +2162,9 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
<< "PySide::Signal::updateSourceObject(self);\n"
<< "metaObject = cptr->metaObject(); // <- init python qt properties\n"
<< "if (!errInfo.isNull() && PyDict_Check(errInfo.object())) {\n" << indent
- << "if (!PySide::fillQtProperties(self, metaObject, errInfo))\n" << indent
- << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent << outdent
+ << "if (!PySide::fillQtProperties(self, metaObject, errInfo, usesPyMI))\n" << indent
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent << outdent
<< "};\n";
}
@@ -2190,31 +2181,27 @@ void CppGenerator::writeConstructorWrapper(TextStream &s, const OverloadData &ov
}
if (hasCodeInjectionsAtEnd) {
// FIXME: C++ arguments are not available in code injection on constructor when position = end.
- s <<"switch (overloadId) {\n";
+ s << "switch (overloadId) {\n";
for (const auto &func : overloadData.overloads()) {
- Indentation indent(s);
+ s << indent;
const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips();
for (const CodeSnip &cs : injectedCodeSnips) {
if (cs.position == TypeSystem::CodeSnipPositionEnd) {
s << "case " << metaClass->functions().indexOf(func) << ':' << '\n'
- << "{\n";
- {
- Indentation indent(s);
- writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd,
- TypeSystem::TargetLangCode, func,
- true /* usesPyArgs */, nullptr);
- }
- s << "}\nbreak;\n";
+ << "{\n" << indent;
+ writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd,
+ TypeSystem::TargetLangCode, func,
+ true /* usesPyArgs */, nullptr);
+ s << outdent << "}\nbreak;\n";
break;
}
}
+ s << outdent;
}
s << "}\n";
}
s << "\n\nreturn 1;\n";
- if (needsArgumentErrorHandling(overloadData))
- writeErrorSection(s, overloadData, errorReturn);
s<< outdent << "}\n\n";
}
@@ -2227,87 +2214,65 @@ void CppGenerator::writeMethodWrapper(TextStream &s, const OverloadData &overloa
s << "static PyObject *";
s << cpythonFunctionName(rfunc) << "(PyObject *self";
+ bool hasKwdArgs = false;
if (maxArgs > 0) {
s << ", PyObject *"
<< (overloadData.pythonFunctionWrapperUsesListOfArguments() ? u"args"_s : PYTHON_ARG);
- if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator())
+ hasKwdArgs = overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator();
+ if (hasKwdArgs)
s << ", PyObject *kwds";
}
s << ")\n{\n" << indent;
+ if (rfunc->ownerClass() == nullptr || overloadData.hasStaticFunction())
+ s << sbkUnusedVariableCast(PYTHON_SELF_VAR);
+ if (hasKwdArgs)
+ s << sbkUnusedVariableCast("kwds");
writeMethodWrapperPreamble(s, overloadData, classContext);
s << '\n';
- /*
- * This code is intended for shift operations only:
- * Make sure reverse <</>> operators defined in other classes (specially from other modules)
- * are called. A proper and generic solution would require an reengineering in the operator
- * system like the extended converters.
- *
- * Solves #119 - QDataStream <</>> operators not working for QPixmap
- * http://bugs.openbossa.org/show_bug.cgi?id=119
- */
- bool hasReturnValue = overloadData.hasNonVoidReturnType();
- bool callExtendedReverseOperator = hasReturnValue
- && !rfunc->isInplaceOperator()
- && !rfunc->isCallOperator()
- && rfunc->isOperatorOverload();
-
- QScopedPointer<Indentation> reverseIndent;
-
- if (callExtendedReverseOperator) {
- QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc);
- revOpName.insert(2, u'r');
+ // This code is intended for shift operations only: Make sure reverse <</>>
+ // operators defined in other classes (specially from other modules)
+ // are called. A proper and generic solution would require an reengineering
+ // in the operator system like the extended converters.
+ // Solves #119 - QDataStream <</>> operators not working for QPixmap.
+ const bool hasReturnValue = overloadData.hasNonVoidReturnType();
+
+ if (hasReturnValue && rfunc->functionType() == AbstractMetaFunction::ShiftOperator
+ && rfunc->isBinaryOperator()) {
// For custom classes, operations like __radd__ and __rmul__
// will enter an infinite loop.
- if (rfunc->isBinaryOperator() && revOpName.contains(u"shift")) {
- revOpName = u"Shiboken::PyMagicName::"_s + revOpName.replace(u"__"_s, u""_s) + u"()"_s;
- s << "static PyObject *attrName = " << revOpName << ";\n";
- s << "if (!isReverse\n";
- {
- Indentation indent(s);
- s << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")\n"
- << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)\n"
- << "&& PyObject_HasAttr(" << PYTHON_ARG << ", attrName)) {\n";
-
- // This PyObject_CallMethod call will emit lots of warnings like
- // "deprecated conversion from string constant to char *" during compilation
- // due to the method name argument being declared as "char *" instead of "const char *"
- // issue 6952 http://bugs.python.org/issue6952
- s << "PyObject *revOpMethod = PyObject_GetAttr(" << PYTHON_ARG << ", attrName);\n";
- s << "if (revOpMethod && PyCallable_Check(revOpMethod)) {\n";
- {
- Indentation indent(s);
- s << PYTHON_RETURN_VAR << " = PyObject_CallFunction(revOpMethod, \"O\", self);\n"
- << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)"
- << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {\n";
- {
- Indentation indent(s);
- s << "PyErr_Clear();\n"
- << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n"
- << PYTHON_RETURN_VAR << " = " << NULL_PTR << ";\n";
- }
- s << "}\n";
- }
- s << "}\n"
- << "Py_XDECREF(revOpMethod);\n\n";
- } //
- s << "}\n\n"
- << "// Do not enter here if other object has implemented a reverse operator.\n"
- << "if (!" << PYTHON_RETURN_VAR << ") {\n";
- reverseIndent.reset(new Indentation(s));
- } // binary shift operator
- }
-
- if (maxArgs > 0)
- writeOverloadedFunctionDecisor(s, overloadData);
-
- writeFunctionCalls(s, overloadData, classContext, ErrorReturn::Default);
-
- if (!reverseIndent.isNull()) { // binary shift operator
- reverseIndent.reset();
- s << '\n' << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n";
+ const QString pythonOp = ShibokenGenerator::pythonOperatorFunctionName(rfunc);
+ s << "static PyObject *attrName = Shiboken::PyMagicName::r"
+ << pythonOp.mid(2, pythonOp.size() -4) << "();\n" // Strip __
+ << "if (!isReverse\n" << indent
+ << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")\n"
+ << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)\n"
+ << "&& PyObject_HasAttr(" << PYTHON_ARG << ", attrName)) {\n"
+ << "PyObject *revOpMethod = PyObject_GetAttr(" << PYTHON_ARG << ", attrName);\n"
+ << "if (revOpMethod && PyCallable_Check(revOpMethod)) {\n" << indent
+ << PYTHON_RETURN_VAR << " = PyObject_CallFunction(revOpMethod, \"O\", self);\n"
+ << "if (" << shibokenErrorsOccurred
+ << " && (PyErr_ExceptionMatches(PyExc_NotImplementedError)"
+ << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {\n" << indent
+ << "PyErr_Clear();\n"
+ << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n"
+ << PYTHON_RETURN_VAR << " = " << NULL_PTR << ";\n"
+ << outdent << "}\n"
+ << outdent << "}\n"
+ << "Py_XDECREF(revOpMethod);\n\n"
+ << outdent << "}\n\n"
+ << "// Do not enter here if other object has implemented a reverse operator.\n"
+ << "if (" << PYTHON_RETURN_VAR << " == nullptr) {\n" << indent;
+ if (maxArgs > 0)
+ writeOverloadedFunctionDecisor(s, overloadData, ErrorReturn::Default);
+ writeFunctionCalls(s, overloadData, classContext, ErrorReturn::Default);
+ s << outdent << '\n' << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n";
+ } else { // binary shift operator
+ if (maxArgs > 0)
+ writeOverloadedFunctionDecisor(s, overloadData, ErrorReturn::Default);
+ writeFunctionCalls(s, overloadData, classContext, ErrorReturn::Default);
}
s << '\n';
@@ -2325,9 +2290,6 @@ void CppGenerator::writeMethodWrapper(TextStream &s, const OverloadData &overloa
s << "Py_RETURN_NONE;\n";
}
- if (needsArgumentErrorHandling(overloadData))
- writeErrorSection(s, overloadData, ErrorReturn::Default);
-
s<< outdent << "}\n\n";
}
@@ -2335,8 +2297,7 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData &
ErrorReturn errorReturn)
{
const auto rfunc = overloadData.referenceFunction();
- s << "PyTuple_GET_SIZE(args);\n";
- writeUnusedVariableCast(s, u"numArgs"_s);
+ s << "PyTuple_GET_SIZE(args);\n" << sbkUnusedVariableCast("numArgs");
int minArgs = overloadData.minArgs();
int maxArgs = overloadData.maxArgs();
@@ -2365,15 +2326,16 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData &
// Disable argument count checks for QObject constructors to allow for
// passing properties as KW args.
- auto *owner = rfunc->ownerClass();
- bool isQObjectConstructor = owner != nullptr && owner->isQObject()
+ const auto owner = rfunc->ownerClass();
+ bool isQObjectConstructor = owner && isQObject(owner)
&& rfunc->functionType() == AbstractMetaFunction::ConstructorFunction;
if (usesNamedArguments && !isQObjectConstructor) {
s << "errInfo.reset(Shiboken::checkInvalidArgumentCount(numArgs, "
<< minArgs << ", " << maxArgs << "));\n"
<< "if (!errInfo.isNull())\n" << indent
- << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent;
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent;
}
const QList<int> invalidArgsLength = overloadData.invalidArgumentLengths();
@@ -2385,7 +2347,8 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData &
s << "numArgs == " << invalidArgsLength.at(i);
}
s << ")\n" << indent
- << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent;
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent;
}
s << '\n';
@@ -2396,7 +2359,7 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData &
funcName = rfunc->name();
QString argsVar = overloadData.hasVarargs() ? u"nonvarargs"_s : u"args"_s;
- s << "if (!";
+ s << "if (";
if (usesNamedArguments) {
s << "PyArg_ParseTuple(" << argsVar << ", \"|" << QByteArray(maxArgs, 'O')
<< ':' << funcName << '"';
@@ -2406,7 +2369,7 @@ void CppGenerator::writeArgumentsInitializer(TextStream &s, const OverloadData &
}
for (int i = 0; i < maxArgs; i++)
s << ", &(" << PYTHON_ARGS << '[' << i << "])";
- s << "))\n" << indent << errorReturn << outdent << '\n';
+ s << ") == 0)\n" << indent << errorReturn << outdent << '\n';
}
void CppGenerator::writeCppSelfConversion(TextStream &s, const GeneratorContext &context,
@@ -2417,23 +2380,15 @@ void CppGenerator::writeCppSelfConversion(TextStream &s, const GeneratorContext
return;
}
- static const QString pythonSelfVar = u"self"_s;
if (useWrapperClass)
s << "static_cast<" << className << " *>(";
- s << cpythonWrapperCPtr(context.metaClass(), pythonSelfVar);
+ s << cpythonWrapperCPtr(context.metaClass(), PYTHON_SELF_VAR);
if (useWrapperClass)
s << ')';
}
-void CppGenerator::writeSmartPointerCppSelfConversion(TextStream &s,
- const GeneratorContext &context)
-{
- Q_ASSERT(context.forSmartPointer());
- s << cpythonWrapperCPtr(context.preciseType(), u"self"_s);
-}
-
-static inline void writeCppSelfVarDef(TextStream &s,
- CppGenerator::CppSelfDefinitionFlags flags = {})
+void CppGenerator::writeCppSelfVarDef(TextStream &s,
+ CppSelfDefinitionFlags flags)
{
if (flags.testFlag(CppGenerator::CppSelfAsReference))
s << "auto &" << CPP_SELF_VAR << " = *";
@@ -2441,22 +2396,10 @@ static inline void writeCppSelfVarDef(TextStream &s,
s << "auto *" << CPP_SELF_VAR << " = ";
}
-void CppGenerator::writeSmartPointerCppSelfDefinition(TextStream &s,
- const GeneratorContext &context,
- ErrorReturn errorReturn,
- CppSelfDefinitionFlags flags)
-{
- Q_ASSERT(context.forSmartPointer());
- writeInvalidPyObjectCheck(s, u"self"_s, errorReturn);
- writeCppSelfVarDef(s, flags);
- writeSmartPointerCppSelfConversion(s, context);
- s << ";\n";
-}
-
void CppGenerator::writeCppSelfDefinition(TextStream &s,
const GeneratorContext &context,
ErrorReturn errorReturn,
- CppSelfDefinitionFlags flags) const
+ CppSelfDefinitionFlags flags)
{
Q_ASSERT(!(flags.testFlag(CppSelfAsReference) && flags.testFlag(HasStaticOverload)));
if (context.forSmartPointer()) {
@@ -2464,7 +2407,7 @@ void CppGenerator::writeCppSelfDefinition(TextStream &s,
return;
}
- const AbstractMetaClass *metaClass = context.metaClass();
+ AbstractMetaClassCPtr metaClass = context.metaClass();
const auto cppWrapper = context.metaClass()->cppWrapper();
// In the Python method, use the wrapper to access the protected
// functions.
@@ -2472,10 +2415,9 @@ void CppGenerator::writeCppSelfDefinition(TextStream &s,
&& cppWrapper.testFlag(AbstractMetaClass::CppProtectedHackWrapper);
Q_ASSERT(!useWrapperClass || context.useWrapper());
const QString className = useWrapperClass
- ? context.wrapperName()
- : (u"::"_s + metaClass->qualifiedCppName());
+ ? context.wrapperName() : getFullTypeName(metaClass);
- writeInvalidPyObjectCheck(s, u"self"_s, errorReturn);
+ writeInvalidPyObjectCheck(s, PYTHON_SELF_VAR, errorReturn);
if (flags.testFlag(CppSelfAsReference)) {
writeCppSelfVarDef(s, flags);
@@ -2489,76 +2431,71 @@ void CppGenerator::writeCppSelfDefinition(TextStream &s,
// PYSIDE-131: The single case of a class method for now: tr().
writeCppSelfVarDef(s, flags);
writeCppSelfConversion(s, context, className, useWrapperClass);
- s << ";\n";
- writeUnusedVariableCast(s, CPP_SELF_VAR);
+ s << ";\n" << sbkUnusedVariableCast(CPP_SELF_VAR);
}
return;
}
- s << className << " *" << CPP_SELF_VAR << " = nullptr;\n";
- writeUnusedVariableCast(s, CPP_SELF_VAR);
+ s << className << " *" << CPP_SELF_VAR << " = nullptr;\n"
+ << sbkUnusedVariableCast(CPP_SELF_VAR);
// Checks if the underlying C++ object is valid.
- s << "if (self)\n";
- {
- Indentation indent(s);
- s << CPP_SELF_VAR << " = ";
- writeCppSelfConversion(s, context, className, useWrapperClass);
- s << ";\n";
- }
+ s << "if (self)\n" << indent
+ << CPP_SELF_VAR << " = ";
+ writeCppSelfConversion(s, context, className, useWrapperClass);
+ s << ";\n"<< outdent;
}
void CppGenerator::writeCppSelfDefinition(TextStream &s,
const AbstractMetaFunctionCPtr &func,
const GeneratorContext &context,
ErrorReturn errorReturn,
- CppSelfDefinitionFlags flags) const
+ CppSelfDefinitionFlags flags)
{
if (!func->ownerClass() || func->isConstructor())
return;
if (func->isOperatorOverload() && func->isBinaryOperator()) {
QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry());
- s << "bool isReverse = " << checkFunc << PYTHON_ARG << ")\n";
- {
- Indentation indent1(s, 4);
- s << "&& !" << checkFunc << "self);\n";
- }
- s << "if (isReverse)\n";
- Indentation indent(s);
- s << "std::swap(self, " << PYTHON_ARG << ");\n";
+ s << "bool isReverse = " << checkFunc << PYTHON_ARG << ")\n"
+ << " && !" << checkFunc << "self);\n"
+ << "if (isReverse)\n" << indent
+ << "std::swap(self, " << PYTHON_ARG << ");\n" << outdent;
}
writeCppSelfDefinition(s, context, errorReturn, flags);
}
-void CppGenerator::writeErrorSection(TextStream &s, const OverloadData &overloadData,
- ErrorReturn errorReturn)
+QString CppGenerator::returnErrorWrongArguments(const OverloadData &overloadData,
+ ErrorReturn errorReturn)
{
const auto rfunc = overloadData.referenceFunction();
- s << '\n' << cpythonFunctionName(rfunc) << "_TypeError:\n";
- Indentation indentation(s);
QString argsVar = overloadData.pythonFunctionWrapperUsesListOfArguments()
? u"args"_s : PYTHON_ARG;
- s << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", fullName, errInfo);\n"
- << errorReturn;
+ switch (errorReturn) {
+ case ErrorReturn::Default:
+ return u"Shiboken::returnWrongArguments("_s + argsVar + u", fullName, errInfo)"_s;
+ case ErrorReturn::Zero:
+ return u"Shiboken::returnWrongArguments_Zero("_s + argsVar + u", fullName, errInfo)"_s;
+ case ErrorReturn::MinusOne:
+ return u"Shiboken::returnWrongArguments_MinusOne("_s + argsVar + u", fullName, errInfo)"_s;
+ case ErrorReturn::Void:
+ Q_ASSERT(false);
+ }
+ return {};
}
void CppGenerator::writeFunctionReturnErrorCheckSection(TextStream &s,
ErrorReturn errorReturn,
bool hasReturnValue)
{
- s << "if (PyErr_Occurred()";
+ s << "if (" << shibokenErrorsOccurred;
if (hasReturnValue)
- s << " || !" << PYTHON_RETURN_VAR;
- s << ") {\n";
- {
- Indentation indent(s);
- if (hasReturnValue)
- s << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n";
- s << errorReturn;
- }
- s << "}\n";
+ s << " || " << PYTHON_RETURN_VAR << " == nullptr";
+ s << ") {\n" << indent;
+ if (hasReturnValue)
+ s << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n";
+ s << errorReturn << outdent << "}\n";
}
void CppGenerator::writeInvalidPyObjectCheck(TextStream &s, const QString &pyObj,
@@ -2604,7 +2541,7 @@ void CppGenerator::writeTypeCheck(TextStream &s, const AbstractMetaType &argType
if (!argType.typeEntry()->isCustom()) {
typeCheck = u'(' + pythonToCppConverterForArgumentName(argumentName)
+ u" = "_s + typeCheck + u"))"_s;
- if (!isNumber && argType.typeEntry()->isCppPrimitive()) {
+ if (!isNumber && isCppPrimitive(argType.typeEntry())) {
typeCheck.prepend(cpythonCheckFunction(argType) + u'('
+ argumentName + u") && "_s);
}
@@ -2662,10 +2599,10 @@ static void checkTypeViability(const AbstractMetaFunctionCPtr &func)
}
void CppGenerator::writeTypeCheck(TextStream &s,
- const QSharedPointer<OverloadDataNode> &overloadData,
+ const std::shared_ptr<OverloadDataNode> &overloadData,
const QString &argumentName)
{
- QSet<const TypeEntry *> numericTypes;
+ QSet<TypeEntryCPtr> numericTypes;
const OverloadDataList &siblings = overloadData->parent()->children();
for (const auto &sibling : siblings) {
for (const auto &func : sibling->overloads()) {
@@ -2689,21 +2626,24 @@ void CppGenerator::writeTypeCheck(TextStream &s,
writeTypeCheck(s, argType, argumentName, numberType, rejectNull);
}
-void CppGenerator::writeArgumentConversion(TextStream &s,
- const AbstractMetaType &argType,
- const QString &argName, const QString &pyArgName,
- ErrorReturn errorReturn,
- const AbstractMetaClass *context,
- const QString &defaultValue,
- bool castArgumentAsUnused) const
+qsizetype CppGenerator::writeArgumentConversion(TextStream &s,
+ const AbstractMetaType &argType,
+ const QString &argName,
+ const QString &pyArgName,
+ ErrorReturn errorReturn,
+ const AbstractMetaClassCPtr &context,
+ const QString &defaultValue,
+ bool castArgumentAsUnused) const
{
+ qsizetype result = 0;
if (argType.typeEntry()->isCustom() || argType.typeEntry()->isVarargs())
- return;
+ return result;
if (argType.isWrapperType())
writeInvalidPyObjectCheck(s, pyArgName, errorReturn);
- writePythonToCppTypeConversion(s, argType, pyArgName, argName, context, defaultValue);
+ result = writePythonToCppTypeConversion(s, argType, pyArgName, argName, context, defaultValue);
if (castArgumentAsUnused)
- writeUnusedVariableCast(s, argName);
+ s << sbkUnusedVariableCast(argName);
+ return result;
}
AbstractMetaType
@@ -2723,12 +2663,12 @@ static inline QString arrayHandleType(const AbstractMetaTypeList &nestedArrayTyp
{
switch (nestedArrayTypes.size()) {
case 1:
- return QStringLiteral("Shiboken::Conversions::ArrayHandle<")
+ return "Shiboken::Conversions::ArrayHandle<"_L1
+ nestedArrayTypes.constLast().minimalSignature() + u'>';
case 2:
- return QStringLiteral("Shiboken::Conversions::Array2Handle<")
+ return "Shiboken::Conversions::Array2Handle<"_L1
+ nestedArrayTypes.constLast().minimalSignature()
- + QStringLiteral(", ")
+ + ", "_L1
+ QString::number(nestedArrayTypes.constFirst().arrayElementCount())
+ u'>';
}
@@ -2767,51 +2707,24 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
const AbstractMetaType &type,
const QString &pyIn,
const QString &cppOut,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
const QString &defaultValue) const
{
- const TypeEntry *typeEntry = type.typeEntry();
+ TypeEntryCPtr typeEntry = type.typeEntry();
if (typeEntry->isCustom() || typeEntry->isVarargs())
return 0;
- qsizetype indirections = -type.indirectionsV().size();
+ const auto arg = GeneratorArgument::fromMetaType(type);
+ const bool isPrimitive = arg.type == GeneratorArgument::Type::Primitive;
QString cppOutAux = cppOut + u"_local"_s;
- const bool isPrimitive = typeEntry->isPrimitive();
- const bool isEnum = typeEntry->isEnum();
- const bool isFlags = typeEntry->isFlags();
- const bool treatAsPointer = type.valueTypeWithCopyConstructorOnlyPassed();
- const bool isContainer = typeEntry->isContainer();
- bool isPointerOrObjectType = (type.isObjectType() || type.isPointer())
- && !type.isUserPrimitive() && !type.isExtendedCppPrimitive()
- && !isEnum && !isFlags;
- const bool isNotContainerEnumOrFlags = !isContainer
- && !isEnum && !isFlags;
- const bool mayHaveImplicitConversion = type.referenceType() == LValueReference
- && !type.isUserPrimitive()
- && !type.isExtendedCppPrimitive()
- && isNotContainerEnumOrFlags
- && !(treatAsPointer || isPointerOrObjectType);
-
- // For implicit conversions or containers, either value or pointer conversion
- // may occur. An implicit conversion uses value conversion whereas the object
- // itself uses pointer conversion. For containers, the PyList/container
- // conversion is by value whereas opaque containers use pointer conversion.
- // For a container passed by pointer, a local variable is also needed.
- const bool valueOrPointer = mayHaveImplicitConversion
- || type.generateOpaqueContainer()
- || (isContainer && indirections != 0);
-
- const AbstractMetaTypeList &nestedArrayTypes = type.nestedArrayTypes();
- const bool isCppPrimitiveArray = !nestedArrayTypes.isEmpty()
- && nestedArrayTypes.constLast().isCppPrimitive();
- QString typeName = isCppPrimitiveArray
- ? arrayHandleType(nestedArrayTypes)
- : getFullTypeNameWithoutModifiers(type);
+ QString typeName = arg.type == GeneratorArgument::Type::CppPrimitiveArray
+ ? arrayHandleType(type.nestedArrayTypes())
+ : getFullTypeNameWithoutModifiers(type);
bool isProtectedEnum = false;
- if (isEnum && avoidProtectedHack()) {
+ if (arg.type == GeneratorArgument::Type::Enum && avoidProtectedHack()) {
auto metaEnum = api().findAbstractMetaEnum(type.typeEntry());
if (metaEnum.has_value() && metaEnum->isProtected()) {
typeName = wrapperName(context) + u"::"_s
@@ -2821,19 +2734,21 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
}
s << typeName;
- if (isCppPrimitiveArray) {
+ switch (arg.conversion) {
+ case GeneratorArgument::Conversion::CppPrimitiveArray:
s << ' ' << cppOut;
- } else if (valueOrPointer) {
- ++indirections;
+ break;
+ case GeneratorArgument::Conversion::ValueOrPointer: {
// Generate either value conversion for &cppOutAux or pointer
// conversion for &cppOut
s << ' ' << cppOutAux;
// No default value for containers which can also be passed by pointer.
- if (!isContainer)
+ if (arg.type != GeneratorArgument::Type::Container || type.indirections() == 0)
writeMinimalConstructorExpression(s, api(), type, isPrimitive, defaultValue);
s << ";\n" << typeName << " *" << cppOut << " = &" << cppOutAux;
- } else if (treatAsPointer || isPointerOrObjectType) {
- ++indirections;
+ }
+ break;
+ case GeneratorArgument::Conversion::Pointer: {
s << " *" << cppOut;
if (!defaultValue.isEmpty()) {
const bool needsConstCast = !isNullPtr(defaultValue)
@@ -2846,7 +2761,9 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
if (needsConstCast)
s << ')';
}
- } else {
+ }
+ break;
+ case GeneratorArgument::Conversion::Default:
s << ' ' << cppOut;
if (isProtectedEnum && avoidProtectedHack()) {
s << " = ";
@@ -2854,11 +2771,14 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
s << "{}";
else
s << defaultValue;
- } else if (type.isUserPrimitive() || isEnum || isFlags) {
+ } else if (type.isUserPrimitive()
+ || arg.type == GeneratorArgument::Type::Enum
+ || arg.type == GeneratorArgument::Type::Flags) {
writeMinimalConstructorExpression(s, api(), typeEntry, isPrimitive, defaultValue);
- } else if (!type.isContainer() && !type.isSmartPointer()) {
+ } else if ((!type.isContainer() || type.indirections() == 0) && !type.isSmartPointer()) {
writeMinimalConstructorExpression(s, api(), type, isPrimitive, defaultValue);
}
+ break;
}
s << ";\n";
@@ -2866,7 +2786,7 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
QString pythonToCppCall = pythonToCppFunc + u'(' + pyIn + u", &"_s
+ cppOut + u')';
- if (!valueOrPointer) {
+ if (arg.conversion != GeneratorArgument::Conversion::ValueOrPointer) {
// pythonToCppFunc may be 0 when less parameters are passed and
// the defaultValue takes effect.
if (!defaultValue.isEmpty())
@@ -2874,7 +2794,7 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
s << pythonToCppCall << ";\n";
if (!defaultValue.isEmpty())
s << outdent;
- return indirections;
+ return arg.indirections;
}
// pythonToCppFunc may be 0 when less parameters are passed and
@@ -2892,7 +2812,7 @@ qsizetype CppGenerator::writePythonToCppTypeConversion(TextStream &s,
else
s << "}\n" << outdent;
- return indirections;
+ return arg.indirections;
}
static void addConversionRuleCodeSnippet(CodeSnipList &snippetList, QString &rule,
@@ -2950,7 +2870,9 @@ void CppGenerator::writeNoneReturn(TextStream &s, const AbstractMetaFunctionCPtr
}
}
-void CppGenerator::writeOverloadedFunctionDecisor(TextStream &s, const OverloadData &overloadData) const
+void CppGenerator::writeOverloadedFunctionDecisor(TextStream &s,
+ const OverloadData &overloadData,
+ ErrorReturn errorReturn) const
{
s << "// Overloaded function decisor\n";
const auto rfunc = overloadData.referenceFunction();
@@ -2960,7 +2882,7 @@ void CppGenerator::writeOverloadedFunctionDecisor(TextStream &s, const OverloadD
s << "// " << i << ": ";
if (func->isStatic())
s << "static ";
- if (const auto *decl = func->declaringClass())
+ if (const auto &decl = func->declaringClass())
s << decl->name() << "::";
s << func->signatureComment() << '\n';
}
@@ -2977,8 +2899,9 @@ void CppGenerator::writeOverloadedFunctionDecisor(TextStream &s, const OverloadD
}
s << "// Function signature not found.\n"
- << "if (overloadId == -1) goto "
- << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;\n\n";
+ << "if (overloadId == -1)\n" << indent
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n\n"
+ << outdent;
}
void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
@@ -3040,21 +2963,17 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
if (hasDefaultCall) {
isFirst = false;
int numArgs = node->argPos() + 1;
- s << "if (numArgs == " << numArgs << ") {\n";
- {
- Indentation indent(s);
- auto func = referenceFunction;
- for (const auto &child : children) {
- const auto defValFunc = child->getFunctionWithDefaultValue();
- if (!defValFunc.isNull()) {
- func = defValFunc;
- break;
- }
+ s << "if (numArgs == " << numArgs << ") {\n" << indent;
+ auto func = referenceFunction;
+ for (const auto &child : children) {
+ const auto defValFunc = child->getFunctionWithDefaultValue();
+ if (defValFunc) {
+ func = defValFunc;
+ break;
}
- s << "overloadId = " << overloadData.functionNumber(func)
- << "; // " << func->minimalSignature() << '\n';
}
- s << '}';
+ s << "overloadId = " << overloadData.functionNumber(func)
+ << "; // " << func->minimalSignature() << '\n' << outdent << '}';
}
for (auto child : children) {
@@ -3074,7 +2993,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
int sequenceArgCount = 0;
while (od && !od->argType().isVarargs()) {
const bool typeReplacedByPyObject = od->isTypeModified()
- && od->modifiedArgType().name() == cPyObjectT();
+ && od->modifiedArgType().name() == cPyObjectT;
if (!typeReplacedByPyObject) {
if (usePyArgs)
pyArgName = pythonArgsAt(od->argPos());
@@ -3082,13 +3001,12 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
auto func = od->referenceFunction();
if (func->isConstructor() && func->arguments().size() == 1) {
- const AbstractMetaClass *ownerClass = func->ownerClass();
- const ComplexTypeEntry *baseContainerType = ownerClass->typeEntry()->baseContainerType();
+ AbstractMetaClassCPtr ownerClass = func->ownerClass();
+ ComplexTypeEntryCPtr baseContainerType = ownerClass->typeEntry()->baseContainerType();
if (baseContainerType && baseContainerType == func->arguments().constFirst().type().typeEntry()
&& ownerClass->isCopyable()) {
- tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ")\n";
- Indentation indent(s);
- tck << "&& ";
+ tck << '!' << cpythonCheckFunction(ownerClass->typeEntry())
+ << pyArgName << ")\n" << indent << "&& " << outdent;
}
}
writeTypeCheck(tck, od, pyArgName);
@@ -3136,15 +3054,11 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
if (typeChecks.isEmpty()) {
s << "true";
} else {
- Indentation indent(s);
- s << typeChecks.join(u"\n&& "_s);
- }
- s << ") {\n";
- {
- Indentation indent(s);
- writeOverloadedFunctionDecisorEngine(s, overloadData, child.data());
+ s << indent << typeChecks.join(u"\n&& "_s) << outdent;
}
- s << "}";
+ s << ") {\n" << indent;
+ writeOverloadedFunctionDecisorEngine(s, overloadData, child.get());
+ s << outdent << '}';
}
s << '\n';
}
@@ -3155,36 +3069,33 @@ void CppGenerator::writeFunctionCalls(TextStream &s, const OverloadData &overloa
{
const AbstractMetaFunctionCList &overloads = overloadData.overloads();
s << "// Call function/method\n"
- << (overloads.size() > 1 ? "switch (overloadId) " : "") << "{\n";
- {
- Indentation indent(s);
- if (overloads.size() == 1) {
- writeSingleFunctionCall(s, overloadData, overloads.constFirst(), context,
- errorReturn);
- } else {
- for (qsizetype i = 0; i < overloads.size(); ++i) {
- const auto func = overloads.at(i);
- s << "case " << i << ": // " << func->signature() << "\n{\n";
- {
- Indentation indent(s);
- writeSingleFunctionCall(s, overloadData, func, context, errorReturn);
- s << "break;\n";
- }
- s << "}\n";
- }
+ << (overloads.size() > 1 ? "switch (overloadId) " : "") << "{\n" << indent;
+ if (overloads.size() == 1) {
+ writeSingleFunctionCall(s, overloadData, overloads.constFirst(), context,
+ errorReturn);
+ } else {
+ for (qsizetype i = 0; i < overloads.size(); ++i) {
+ const auto func = overloads.at(i);
+ s << "case " << i << ": // " << func->signature() << "\n{\n" << indent;
+ writeSingleFunctionCall(s, overloadData, func, context, errorReturn);
+ s << "break;\n" << outdent << "}\n";
}
}
- s << "}\n";
+ s << outdent << "}\n";
}
static void writeDeprecationWarning(TextStream &s,
const GeneratorContext &context,
- const AbstractMetaFunctionCPtr &func)
+ const AbstractMetaFunctionCPtr &func,
+ CppGenerator::ErrorReturn errorReturn)
{
s << "Shiboken::Warnings::warnDeprecated(\"";
- if (auto *cls = context.metaClass())
+ if (const auto cls = context.metaClass())
s << cls->name() << "\", ";
- s << '"' << func->signature().replace(u"::"_s, u"."_s) << "\");\n";
+ // Check error in case "warning-as-error" is set.
+ s << '"' << func->signature().replace(u"::"_s, u"."_s) << "\");\n"
+ << "if (" << shibokenErrorsOccurred << ")\n"
+ << indent << errorReturn << outdent;
}
void CppGenerator::writeSingleFunctionCall(TextStream &s,
@@ -3194,7 +3105,7 @@ void CppGenerator::writeSingleFunctionCall(TextStream &s,
ErrorReturn errorReturn) const
{
if (func->isDeprecated())
- writeDeprecationWarning(s, context, func);
+ writeDeprecationWarning(s, context, func, errorReturn);
if (func->functionType() == AbstractMetaFunction::EmptyFunction) {
s << "Shiboken::Errors::setPrivateMethod(\""
@@ -3206,22 +3117,24 @@ void CppGenerator::writeSingleFunctionCall(TextStream &s,
const bool usePyArgs = overloadData.pythonFunctionWrapperUsesListOfArguments();
// Handle named arguments.
- writeNamedArgumentResolution(s, func, usePyArgs, overloadData);
+ writeNamedArgumentResolution(s, func, usePyArgs, overloadData, errorReturn);
bool injectCodeCallsFunc = injectedCodeCallsCppFunction(context, func);
bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc;
int removedArgs = 0;
- for (qsizetype argIdx = 0; argIdx < func->arguments().size(); ++argIdx) {
+
+ const auto argCount = func->arguments().size();
+ QList<qsizetype> indirections(argCount, 0);
+ for (qsizetype argIdx = 0; argIdx < argCount; ++argIdx) {
const bool hasConversionRule =
func->hasConversionRule(TypeSystem::NativeCode, int(argIdx + 1));
const AbstractMetaArgument &arg = func->arguments().at(argIdx);
if (arg.isModifiedRemoved()) {
if (!arg.defaultValueExpression().isEmpty()) {
- const QString cppArgRemoved = CPP_ARG_REMOVED
- + QString::number(argIdx);
+ const QString cppArgRemoved = CPP_ARG_REMOVED(argIdx);
s << getFullTypeName(arg.type()) << ' ' << cppArgRemoved;
- s << " = " << arg.defaultValueExpression() << ";\n";
- writeUnusedVariableCast(s, cppArgRemoved);
+ s << " = " << arg.defaultValueExpression() << ";\n"
+ << sbkUnusedVariableCast(cppArgRemoved);
} else if (!injectCodeCallsFunc && !func->isUserAdded() && !hasConversionRule) {
// When an argument is removed from a method signature and no other means of calling
// the method are provided (as with code injection) the generator must abort.
@@ -3240,21 +3153,21 @@ void CppGenerator::writeSingleFunctionCall(TextStream &s,
continue;
auto argType = getArgumentType(func, argIdx);
int argPos = argIdx - removedArgs;
- QString argName = CPP_ARG + QString::number(argPos);
QString pyArgName = usePyArgs ? pythonArgsAt(argPos) : PYTHON_ARG;
- writeArgumentConversion(s, argType, argName, pyArgName, errorReturn,
- func->implementingClass(), arg.defaultValueExpression(),
- func->isUserAdded());
+ indirections[argIdx] =
+ writeArgumentConversion(s, argType, CPP_ARG_N(argPos), pyArgName, errorReturn,
+ func->implementingClass(), arg.defaultValueExpression(),
+ func->isUserAdded());
}
s << '\n';
int numRemovedArgs = OverloadData::numberOfRemovedArguments(func);
- s << "if (!PyErr_Occurred()) {\n" << indent;
+ s << "if (Shiboken::Errors::occurred() == nullptr) {\n" << indent;
writeMethodCall(s, func, context,
overloadData.pythonFunctionWrapperUsesListOfArguments(),
- func->arguments().size() - numRemovedArgs, errorReturn);
+ func->arguments().size() - numRemovedArgs, indirections, errorReturn);
if (!func->isConstructor())
writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
@@ -3276,8 +3189,8 @@ QString CppGenerator::pythonToCppFunctionName(const AbstractMetaType &sourceType
{
return pythonToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType));
}
-QString CppGenerator::pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion *toNative,
- const TypeEntry *targetType)
+QString CppGenerator::pythonToCppFunctionName(const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType)
{
return pythonToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType));
}
@@ -3291,8 +3204,8 @@ QString CppGenerator::convertibleToCppFunctionName(const AbstractMetaType &sourc
{
return convertibleToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType));
}
-QString CppGenerator::convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion *toNative,
- const TypeEntry *targetType)
+QString CppGenerator::convertibleToCppFunctionName(const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType)
{
return convertibleToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType));
}
@@ -3302,9 +3215,10 @@ void CppGenerator::writeCppToPythonFunction(TextStream &s, const QString &code,
{
QString prettyCode = code;
- processCodeSnip(prettyCode);
+ const QString funcName = cppToPythonFunctionName(sourceTypeName, targetTypeName);
+ processCodeSnip(prettyCode, funcName);
- s << "static PyObject *" << cppToPythonFunctionName(sourceTypeName, targetTypeName)
+ s << "static PyObject *" << funcName
<< "(const void *cppIn)\n{\n" << indent << prettyCode
<< ensureEndl << outdent << "}\n";
}
@@ -3333,28 +3247,39 @@ static void replaceCppToPythonVariables(QString &code, const QString &typeName,
code.replace(u"%out"_s, u"pyOut"_s);
}
-void CppGenerator::writeCppToPythonFunction(TextStream &s, const CustomConversion *customConversion) const
+void CppGenerator::writeCppToPythonFunction(TextStream &s,
+ const CustomConversionPtr &customConversion) const
{
QString code = customConversion->nativeToTargetConversion();
- auto *ownerType = customConversion->ownerType();
+ auto ownerType = customConversion->ownerType();
const bool constRef = !ownerType->isPrimitive(); // PyCapsule needs a non-const ref
replaceCppToPythonVariables(code, getFullTypeName(ownerType), constRef);
writeCppToPythonFunction(s, code, fixedCppTypeName(customConversion->ownerType()));
}
+
+QString CppGenerator::containerNativeToTargetTypeName(const ContainerTypeEntryCPtr &type)
+{
+ QString result = type->targetLangApiName();
+ if (result != cPyObjectT) {
+ result = containerCpythonBaseName(type);
+ if (result == cPySequenceT)
+ result = cPyListT;
+ }
+ return result;
+}
+
void CppGenerator::writeCppToPythonFunction(TextStream &s, const AbstractMetaType &containerType) const
{
- const CustomConversion *customConversion = containerType.typeEntry()->customConversion();
- if (!customConversion) {
+ Q_ASSERT(containerType.typeEntry()->isContainer());
+ auto cte = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
+ if (!cte->hasCustomConversion()) {
QString m;
QTextStream(&m) << "Can't write the C++ to Python conversion function for container type '"
<< containerType.typeEntry()->qualifiedCppName()
<< "' - no conversion rule was defined for it in the type system.";
throw Exception(m);
}
- if (!containerType.typeEntry()->isContainer()) {
- writeCppToPythonFunction(s, customConversion);
- return;
- }
+ const auto customConversion = cte->customConversion();
QString code = customConversion->nativeToTargetConversion();
for (qsizetype i = 0; i < containerType.instantiations().size(); ++i) {
const AbstractMetaType &type = containerType.instantiations().at(i);
@@ -3364,16 +3289,18 @@ void CppGenerator::writeCppToPythonFunction(TextStream &s, const AbstractMetaTyp
code.replace(u"%INTYPE_"_s + QString::number(i), typeName);
}
replaceCppToPythonVariables(code, getFullTypeNameWithoutModifiers(containerType), true);
- processCodeSnip(code);
- writeCppToPythonFunction(s, code, fixedCppTypeName(containerType));
+ processCodeSnip(code, containerType.typeEntry()->qualifiedCppName());
+ writeCppToPythonFunction(s, code, fixedCppTypeName(containerType),
+ containerNativeToTargetTypeName(cte));
}
void CppGenerator::writePythonToCppFunction(TextStream &s, const QString &code, const QString &sourceTypeName,
const QString &targetTypeName) const
{
QString prettyCode = code;
- processCodeSnip(prettyCode);
- s << "static void " << pythonToCppFunctionName(sourceTypeName, targetTypeName)
+ const QString funcName = pythonToCppFunctionName(sourceTypeName, targetTypeName);
+ processCodeSnip(prettyCode, funcName);
+ s << "static void " << funcName
<< "(PyObject *pyIn, void *cppOut)\n{\n" << indent << prettyCode
<< ensureEndl << outdent << "}\n";
}
@@ -3391,16 +3318,15 @@ void CppGenerator::writeIsPythonConvertibleToCppFunction(TextStream &s,
s << "static PythonToCppFunc " << convertibleToCppFunctionName(sourceTypeName, targetTypeName);
s << "(PyObject *pyIn)\n{\n" << indent;
if (acceptNoneAsCppNull) {
- s << "if (pyIn == Py_None)\n";
- Indentation indent(s);
- s << "return Shiboken::Conversions::nonePythonToCppNullPtr;\n";
- }
- s << "if (" << condition << ")\n";
- {
- Indentation indent(s);
- s << "return " << pythonToCppFuncName << ";\n";
+ s << "if (pyIn == Py_None)\n" << indent
+ << "return Shiboken::Conversions::nonePythonToCppNullPtr;\n" << outdent;
+ } else {
+ if (!condition.contains(u"pyIn"))
+ s << sbkUnusedVariableCast("pyIn");
}
- s << "return {};\n" << outdent << "}\n";
+ s << "if (" << condition << ")\n" << indent
+ << "return " << pythonToCppFuncName << ";\n" << outdent
+ << "return {};\n" << outdent << "}\n";
}
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
@@ -3422,7 +3348,9 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
? targetType.cppSignature()
: getFullTypeName(targetType.typeEntry());
c << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = "
- << fullTypeName << '(' << conversion << ");";
+ << fullTypeName << '('
+ << (sourceType.isUniquePointer() ? stdMove(conversion) : conversion)
+ << ");";
QString sourceTypeName = fixedCppTypeName(sourceType);
QString targetTypeName = fixedCppTypeName(targetType);
writePythonToCppFunction(s, c.toString(), sourceTypeName, targetTypeName);
@@ -3435,16 +3363,16 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
}
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
- const CustomConversion::TargetToNativeConversion *toNative,
- const TypeEntry *targetType) const
+ const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType) const
{
// Python to C++ conversion function.
- QString code = toNative->conversion();
+ QString code = toNative.conversion();
QString inType;
- if (toNative->sourceType())
- inType = cpythonTypeNameExt(toNative->sourceType());
+ if (toNative.sourceType())
+ inType = cpythonTypeNameExt(toNative.sourceType());
else
- inType = u'(' + toNative->sourceTypeName() + u"_TypeF())"_s;
+ inType = u'(' + toNative.sourceTypeName() + u"_TypeF())"_s;
code.replace(u"%INTYPE"_s, inType);
code.replace(u"%OUTTYPE"_s, targetType->qualifiedCppName());
code.replace(u"%in"_s, u"pyIn"_s);
@@ -3456,46 +3384,45 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// Python to C++ convertible check function.
- QString typeCheck = toNative->sourceTypeCheck();
+ QString typeCheck = toNative.sourceTypeCheck();
if (typeCheck.isEmpty()) {
- QString pyTypeName = toNative->sourceTypeName();
+ QString pyTypeName = toNative.sourceTypeName();
if (pyTypeName == u"Py_None" || pyTypeName == u"PyNone")
typeCheck = u"%in == Py_None"_s;
- else if (pyTypeName == u"SbkEnumType")
- typeCheck = u"Shiboken::isShibokenEnum(%in)"_s;
else if (pyTypeName == u"SbkObject")
typeCheck = u"Shiboken::Object::checkType(%in)"_s;
}
if (typeCheck.isEmpty()) {
- if (!toNative->sourceType() || toNative->sourceType()->isPrimitive()) {
+ if (!toNative.sourceType() || toNative.sourceType()->isPrimitive()) {
QString m;
QTextStream(&m) << "User added implicit conversion for C++ type '" << targetType->qualifiedCppName()
<< "' must provide either an input type check function or a non primitive type entry.";
throw Exception(m);
}
typeCheck = u"PyObject_TypeCheck(%in, "_s
- + cpythonTypeNameExt(toNative->sourceType()) + u')';
+ + cpythonTypeNameExt(toNative.sourceType()) + u')';
}
typeCheck.replace(u"%in"_s, u"pyIn"_s);
- processCodeSnip(typeCheck);
+ processCodeSnip(typeCheck, targetType->qualifiedCppName());
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
}
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const AbstractMetaType &containerType) const
{
- const CustomConversion *customConversion = containerType.typeEntry()->customConversion();
- if (!customConversion) {
- //qFatal
- return;
- }
- const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
- if (toCppConversions.isEmpty()) {
- //qFatal
- return;
- }
+ Q_ASSERT(containerType.typeEntry()->isContainer());
+ const auto cte = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
+ const auto customConversion = cte->customConversion();
+ for (const auto &conv : customConversion->targetToNativeConversions())
+ writePythonToCppConversionFunction(s, containerType, conv);
+}
+
+void CppGenerator::writePythonToCppConversionFunction(TextStream &s,
+ const AbstractMetaType &containerType,
+ const TargetToNativeConversion &conv) const
+{
// Python to C++ conversion function.
QString cppTypeName = getFullTypeNameWithoutModifiers(containerType);
- QString code = toCppConversions.constFirst()->conversion();
+ QString code = conv.conversion();
const QString line = u"auto &cppOutRef = *reinterpret_cast<"_s
+ cppTypeName + u" *>(cppOut);"_s;
CodeSnipAbstract::prependCode(&code, line);
@@ -3503,7 +3430,8 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const Abst
const AbstractMetaType &type = containerType.instantiations().at(i);
QString typeName = getFullTypeName(type);
// Containers of opaque containers are not handled here.
- if (type.shouldDereferenceArgument() > 0 && !type.generateOpaqueContainer()) {
+ const auto generatorArg = GeneratorArgument::fromMetaType(type);
+ if (generatorArg.indirections > 0 && !type.generateOpaqueContainer()) {
for (int pos = 0; ; ) {
const QRegularExpressionMatch match = convertToCppRegEx().match(code, pos);
if (!match.hasMatch())
@@ -3522,7 +3450,8 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const Abst
code.replace(u"%in"_s, u"pyIn"_s);
code.replace(u"%out"_s, u"cppOutRef"_s);
QString typeName = fixedCppTypeName(containerType);
- writePythonToCppFunction(s, code, typeName, typeName);
+ const QString &sourceTypeName = conv.sourceTypeName();
+ writePythonToCppFunction(s, code, sourceTypeName, typeName);
// Python to C++ convertible check function.
QString typeCheck = cpythonCheckFunction(containerType);
@@ -3530,7 +3459,7 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s, const Abst
typeCheck = u"false"_s;
else
typeCheck = typeCheck + u"pyIn)"_s;
- writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck);
+ writeIsPythonConvertibleToCppFunction(s, sourceTypeName, typeName, typeCheck);
s << '\n';
}
@@ -3562,82 +3491,87 @@ void CppGenerator::writeSetPythonToCppPointerConversion(TextStream &s,
converterVar, pythonToCppFunc, isConvertibleFunc);
}
-void CppGenerator::writeNamedArgumentResolution(TextStream &s, const AbstractMetaFunctionCPtr &func,
- bool usePyArgs, const OverloadData &overloadData)
+// PYSIDE-1986: Some QObject derived classes, (QVBoxLayout) do not have default
+// arguments, which breaks setting properties by named arguments. Force the
+// handling code to be generated nevertheless for applicable widget classes,
+// so that the mechanism of falling through to the error handling to set
+// the properties works nevertheless.
+static bool forceQObjectNamedArguments(const AbstractMetaFunctionCPtr &func)
+{
+ if (func->functionType() != AbstractMetaFunction::ConstructorFunction)
+ return false;
+ const auto owner = func->ownerClass();
+ Q_ASSERT(owner);
+ if (!isQObject(owner))
+ return false;
+ const QString &name = owner->name();
+ return name == u"QVBoxLayout" || name == u"QHBoxLayout"
+ || name == u"QSplitterHandle" || name == u"QSizeGrip";
+}
+
+void CppGenerator::writeNamedArgumentResolution(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ bool usePyArgs,
+ const OverloadData &overloadData,
+ ErrorReturn errorReturn)
{
const AbstractMetaArgumentList &args = OverloadData::getArgumentsWithDefaultValues(func);
- if (args.isEmpty()) {
+ const bool hasDefaultArguments = !args.isEmpty();
+ const bool force = !hasDefaultArguments && usePySideExtensions()
+ && forceQObjectNamedArguments(func);
+ if (!hasDefaultArguments && !force) {
if (overloadData.hasArgumentWithDefaultValue()) {
// PySide-535: Allow for empty dict instead of nullptr in PyPy
- s << "if (kwds && PyDict_Size(kwds) > 0) {\n";
- {
- Indentation indent(s);
- s << "errInfo.reset(kwds);\n"
- << "Py_INCREF(errInfo.object());\n"
- << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
- }
- s << "}\n";
+ s << "if (kwds != nullptr && PyDict_Size(kwds) > 0) {\n" << indent
+ << "errInfo.reset(kwds);\n"
+ << "Py_INCREF(errInfo.object());\n"
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent << "}\n";
}
return;
}
// PySide-535: Allow for empty dict instead of nullptr in PyPy
- s << "if (kwds && PyDict_Size(kwds) > 0) {\n";
- {
- Indentation indent(s);
- s << "PyObject *value{};\n"
- << "Shiboken::AutoDecRef kwds_dup(PyDict_Copy(kwds));\n";
- for (const AbstractMetaArgument &arg : args) {
- const int pyArgIndex = arg.argumentIndex()
- - OverloadData::numberOfRemovedArguments(func, arg.argumentIndex());
- QString pyArgName = usePyArgs ? pythonArgsAt(pyArgIndex)
- : PYTHON_ARG;
- QString pyKeyName = u"key_"_s + arg.name();
- s << "static PyObject *const " << pyKeyName
- << " = Shiboken::String::createStaticString(\"" << arg.name() << "\");\n"
- << "if (PyDict_Contains(kwds, " << pyKeyName << ")) {\n";
- {
- Indentation indent(s);
- s << "value = PyDict_GetItem(kwds, " << pyKeyName << ");\n"
- << "if (value && " << pyArgName << ") {\n";
- {
- Indentation indent(s);
- s << "errInfo.reset(" << pyKeyName << ");\n"
- << "Py_INCREF(errInfo.object());\n"
- << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
- }
- s << "}\nif (value) {\n";
- {
- Indentation indent(s);
- s << pyArgName << " = value;\nif (!";
- const auto &type = arg.modifiedType();
- writeTypeCheck(s, type, pyArgName, isNumber(type.typeEntry()), {});
- s << ")\n";
- {
- Indentation indent(s);
- s << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
- }
- }
- s << "}\nPyDict_DelItem(kwds_dup, " << pyKeyName << ");\n";
- }
- s << "}\n";
- }
- // PYSIDE-1305: Handle keyword args correctly.
- // Normal functions handle their parameters immediately.
- // For constructors that are QObject, we need to delay that
- // until extra keyword signals and properties are handled.
- s << "if (PyDict_Size(kwds_dup) > 0) {\n";
- {
- Indentation indent(s);
- s << "errInfo.reset(kwds_dup.release());\n";
- if (!(func->isConstructor() && func->ownerClass()->isQObject()))
- s << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
- else
- s << "// fall through to handle extra keyword signals and properties\n";
- }
- s << "}\n";
- }
- s << "}\n";
+ s << "if (kwds && PyDict_Size(kwds) > 0) {\n" << indent;
+ if (!force)
+ s << "PyObject *value{};\n";
+ s << "Shiboken::AutoDecRef kwds_dup(PyDict_Copy(kwds));\n";
+ for (const AbstractMetaArgument &arg : args) {
+ const int pyArgIndex = arg.argumentIndex()
+ - OverloadData::numberOfRemovedArguments(func, arg.argumentIndex());
+ QString pyArgName = usePyArgs ? pythonArgsAt(pyArgIndex)
+ : PYTHON_ARG;
+ QString pyKeyName = u"key_"_s + arg.name();
+ s << "static PyObject *const " << pyKeyName
+ << " = Shiboken::String::createStaticString(\"" << arg.name() << "\");\n"
+ << "if (PyDict_Contains(kwds, " << pyKeyName << ") != 0) {\n" << indent
+ << "value = PyDict_GetItem(kwds, " << pyKeyName << ");\n"
+ << "if (value != nullptr && " << pyArgName << " != nullptr ) {\n"
+ << indent << "errInfo.reset(" << pyKeyName << ");\n"
+ << "Py_INCREF(errInfo.object());\n"
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent << "}\nif (value != nullptr) {\n" << indent
+ << pyArgName << " = value;\nif (!";
+ const auto &type = arg.modifiedType();
+ writeTypeCheck(s, type, pyArgName, isNumber(type.typeEntry()), {});
+ s << ")\n" << indent
+ << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n"
+ << outdent << outdent
+ << "}\nPyDict_DelItem(kwds_dup, " << pyKeyName << ");\n"
+ << outdent << "}\n";
+ }
+ // PYSIDE-1305: Handle keyword args correctly.
+ // Normal functions handle their parameters immediately.
+ // For constructors that are QObject, we need to delay that
+ // until extra keyword signals and properties are handled.
+ s << "if (PyDict_Size(kwds_dup) > 0) {\n" << indent
+ << "errInfo.reset(kwds_dup.release());\n";
+ if (!(func->isConstructor() && isQObject(func->ownerClass())))
+ s << "return " << returnErrorWrongArguments(overloadData, errorReturn) << ";\n";
+ else
+ s << "// fall through to handle extra keyword signals and properties\n";
+ s << outdent << "}\n"
+ << outdent << "}\n";
}
QString CppGenerator::argumentNameFromIndex(const ApiExtractorResult &api,
@@ -3645,7 +3579,7 @@ QString CppGenerator::argumentNameFromIndex(const ApiExtractorResult &api,
{
switch (argIndex) {
case -1:
- return u"self"_s;
+ return PYTHON_SELF_VAR;
case 0:
return PYTHON_RETURN_VAR;
case 1: { // Single argument?
@@ -3658,7 +3592,7 @@ QString CppGenerator::argumentNameFromIndex(const ApiExtractorResult &api,
return pythonArgsAt(argIndex - 1);
}
-const AbstractMetaClass *
+AbstractMetaClassCPtr
CppGenerator::argumentClassFromIndex(const ApiExtractorResult &api,
const AbstractMetaFunctionCPtr &func, int argIndex)
{
@@ -3680,25 +3614,45 @@ CppGenerator::argumentClassFromIndex(const ApiExtractorResult &api,
type = type.instantiations().constFirst();
}
- auto *te = type.typeEntry();
+ auto te = type.typeEntry();
if (type.isVoid() || !te->isComplex())
throw Exception(msgInvalidArgumentModification(func, argIndex));
- auto *result = AbstractMetaClass::findClass(api.classes(), te);
+ const auto result = AbstractMetaClass::findClass(api.classes(), te);
if (!result)
throw Exception(msgClassNotFound(te));
return result;
}
+const char tryBlock[] = R"(
+PyObject *errorType{};
+PyObject *errorString{};
+try {
+)";
+
const char defaultExceptionHandling[] = R"(} catch (const std::exception &e) {
- PyErr_SetString(PyExc_RuntimeError, e.what());
+ errorType = PyExc_RuntimeError;
+ errorString = Shiboken::String::fromCString(e.what());
} catch (...) {
- PyErr_SetString(PyExc_RuntimeError, "An unknown exception was caught");
+ errorType = PyExc_RuntimeError;
+ errorString = Shiboken::Messages::unknownException();
}
)";
+const char propagateException[] = R"(
+if (errorType != nullptr)
+ PyErr_SetObject(errorType, errorString);
+)";
+
+static QString explicitConversion(const QString &v, const AbstractMetaType &t)
+{
+ return t.plainType().cppSignature() + u'(' + v + u')';
+}
+
void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr &func,
const GeneratorContext &context, bool usesPyArgs,
- int maxArgs, ErrorReturn errorReturn) const
+ int maxArgs,
+ const QList<qsizetype> &argumentIndirections,
+ ErrorReturn errorReturn) const
{
s << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << '\n';
if (func->isConstructor()) {
@@ -3747,6 +3701,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
writeConversionRule(s, func, TypeSystem::NativeCode, usesPyArgs);
+ bool generateExceptionHandling = false;
+
if (!func->isUserAdded()) {
QStringList userArgs;
if (func->functionType() != AbstractMetaFunction::CopyConstructorFunction) {
@@ -3765,24 +3721,24 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (hasConversionRule)
userArgs << arg.name() + CONV_RULE_OUT_VAR_SUFFIX;
else if (!arg.defaultValueExpression().isEmpty())
- userArgs.append(CPP_ARG_REMOVED + QString::number(i));
+ userArgs.append(CPP_ARG_REMOVED(i));
} else {
if (hasConversionRule) {
userArgs.append(arg.name() + CONV_RULE_OUT_VAR_SUFFIX);
} else {
const int idx = arg.argumentIndex() - removedArgs;
- const auto deRef = arg.type().shouldDereferenceArgument();
- QString argName;
- if (deRef > 0)
- argName += QString(deRef, u'*');
- argName += CPP_ARG + QString::number(idx);
+ const auto deRef = argumentIndirections.at(i);
+ QString argName = AbstractMetaType::dereferencePrefix(deRef)
+ + CPP_ARG_N(idx);
userArgs.append(argName);
}
}
// "Pass unique ptr by value" pattern: Apply std::move()
auto type = arg.type();
- if (type.isUniquePointer() && type.passByValue())
+ if (type.useStdMove())
userArgs.last() = stdMove(userArgs.constLast());
+ else if (type.viewOn() != nullptr)
+ userArgs.last() = explicitConversion(userArgs.constLast(), type);
}
// If any argument's default value was modified the method must be called
@@ -3792,7 +3748,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
QStringList otherArgs;
bool otherArgsModified = false;
bool argsClear = true;
- for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) {
+ for (auto i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) {
const AbstractMetaArgument &arg = func->arguments().at(i);
const bool defValModified = arg.hasModifiedDefaultValueExpression();
const bool hasConversionRule =
@@ -3804,7 +3760,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (hasConversionRule)
otherArgs.prepend(arg.name() + CONV_RULE_OUT_VAR_SUFFIX);
else
- otherArgs.prepend(CPP_ARG_REMOVED + QString::number(i));
+ otherArgs.prepend(CPP_ARG_REMOVED(i));
}
if (otherArgsModified)
userArgs << otherArgs;
@@ -3821,10 +3777,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
firstArg += CPP_SELF_VAR;
firstArg += u')';
QString secondArg = CPP_ARG0;
- if (!func->isUnaryOperator()) {
- auto deRef = func->arguments().constFirst().type().shouldDereferenceArgument();
- AbstractMetaType::applyDereference(&secondArg, deRef);
- }
+ if (!func->isUnaryOperator())
+ AbstractMetaType::applyDereference(&secondArg, argumentIndirections.at(0));
if (func->isUnaryOperator())
std::swap(firstArg, secondArg);
@@ -3854,29 +3808,21 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
Q_ASSERT(owner == context.metaClass());
if (func->functionType() == AbstractMetaFunction::CopyConstructorFunction
&& maxArgs == 1) {
- mc << "new ::" << context.effectiveClassName()
+ mc << "new " << globalScopePrefix(context) << context.effectiveClassName()
<< "(*" << CPP_ARG0 << ')';
} else {
const QString ctorCall = context.effectiveClassName() + u'('
+ userArgs.join(u", "_s) + u')';
- if (usePySideExtensions() && owner->isQObject()) {
+ if (usePySideExtensions() && isQObject(owner)) {
s << "void *addr = PySide::nextQObjectMemoryAddr();\n";
- uva << "if (addr) {\n";
- {
- Indentation indent(uva);
-
- uva << "cptr = new (addr) ::" << ctorCall << ";\n"
- << "PySide::setNextQObjectMemoryAddr(nullptr);"
- << '\n';
- }
- uva << "} else {\n";
- {
- Indentation indent(uva);
- uva << "cptr = new ::" << ctorCall << ";\n";
- }
- uva << "}\n";
+ uva << "if (addr != nullptr) {\n" << indent
+ << "cptr = new (addr) " << globalScopePrefix(context) << ctorCall
+ << ";\nPySide::setNextQObjectMemoryAddr(nullptr);\n" << outdent
+ << "} else {\n" << indent
+ << "cptr = new " << globalScopePrefix(context) << ctorCall << ";\n"
+ << outdent << "}\n";
} else {
- mc << "new ::" << ctorCall;
+ mc << "new " << globalScopePrefix(context) << ctorCall;
}
}
} else {
@@ -3890,7 +3836,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
const bool hasWrapper = shouldGenerateCppWrapper(ownerClass);
if (!avoidProtectedHack() || !func->isProtected() || !hasWrapper) {
if (func->isStatic()) {
- mc << "::" << methodCallClassName << "::";
+ mc << m_gsp << methodCallClassName << "::";
} else {
const QString cppSelfVar = CPP_SELF_VAR;
const QString selfVarCast = func->ownerClass() == func->implementingClass()
@@ -3899,7 +3845,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
+ u" *>("_s + cppSelfVar + u')';
if (func->isConstant()) {
if (avoidProtectedHack()) {
- mc << "const_cast<const ::";
+ mc << "const_cast<const " << globalScopePrefix(context);
if (ownerClass->cppWrapper().testFlag(AbstractMetaClass::CppProtectedHackWrapper)) {
// PYSIDE-500: Need a special wrapper cast when inherited
const QString selfWrapCast = ownerClass == func->implementingClass()
@@ -3914,7 +3860,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
mc << " *>(" << selfVarCast << ")->";
}
} else {
- mc << "const_cast<const ::" << methodCallClassName;
+ mc << "const_cast<const " << m_gsp << methodCallClassName;
mc << " *>(" << selfVarCast << ")->";
}
} else {
@@ -3930,13 +3876,13 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (!func->isStatic()) {
const bool directInheritance = context.metaClass() == ownerClass;
mc << (directInheritance ? "static_cast" : "reinterpret_cast")
- << "<::" << wrapperName(ownerClass) << " *>(" << CPP_SELF_VAR << ")->";
+ << '<' << wrapperName(ownerClass) << " *>("
+ << CPP_SELF_VAR << ")->";
}
if (!func->isAbstract())
mc << (func->isProtected() ? wrapperName(func->ownerClass()) :
- u"::"_s
- + methodCallClassName) << "::";
+ m_gsp + methodCallClassName) << "::";
mc << func->originalName() << "_protected";
}
} else {
@@ -3961,9 +3907,9 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (!injectedCodeCallsCppFunction(context, func)) {
const bool allowThread = func->allowThread();
- const bool generateExceptionHandling = func->generateExceptionHandling();
+ generateExceptionHandling = func->generateExceptionHandling();
if (generateExceptionHandling) {
- s << "try {\n" << indent;
+ s << tryBlock << indent;
if (allowThread) {
s << "Shiboken::ThreadStateSaver threadSaver;\n"
<< "threadSaver.save();\n";
@@ -4043,8 +3989,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (generateExceptionHandling) { // "catch" code
s << outdent << defaultExceptionHandling;
}
- }
- }
+ } // !injected code calls C++ function
+ } // !userAdded
if (func->hasInjectedCode() && !func->isConstructor())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd,
@@ -4071,7 +4017,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
if (!ownership_mods.isEmpty()) {
s << '\n' << "// Ownership transferences.\n";
- for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) {
+ for (const ArgumentModification &arg_mod : std::as_const(ownership_mods)) {
const int argIndex = arg_mod.index();
const QString pyArgName = argumentNameFromIndex(api(), func, argIndex);
@@ -4087,8 +4033,8 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
s << "Shiboken::Object::";
if (ownership == TypeSystem::TargetLangOwnership) {
s << "getOwnership(" << pyArgName << ");";
- } else if (auto *ac = argumentClassFromIndex(api(), func, argIndex);
- ac->hasVirtualDestructor()) {
+ } else if (auto ac = argumentClassFromIndex(api(), func, argIndex);
+ ac && ac->hasVirtualDestructor()) {
s << "releaseOwnership(" << pyArgName << ");";
} else {
s << "invalidate(" << pyArgName << ");";
@@ -4097,7 +4043,7 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
}
} else if (!refcount_mods.isEmpty()) {
- for (const ArgumentModification &arg_mod : qAsConst(refcount_mods)) {
+ for (const ArgumentModification &arg_mod : std::as_const(refcount_mods)) {
ReferenceCount refCount = arg_mod.referenceCounts().constFirst();
if (refCount.action != ReferenceCount::Set
&& refCount.action != ReferenceCount::Remove
@@ -4128,14 +4074,17 @@ void CppGenerator::writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr
}
}
writeParentChildManagement(s, func, usesPyArgs, !hasReturnPolicy);
+
+ if (generateExceptionHandling)
+ s << propagateException;
}
-QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass *metaClass)
+QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClassCPtr &metaClass)
{
QStringList result;
const auto &baseClases = metaClass->typeSystemBaseClasses();
if (!baseClases.isEmpty()) {
- for (const AbstractMetaClass *baseClass : baseClases) {
+ for (const auto &baseClass : baseClases) {
QString offset;
QTextStream(&offset) << "reinterpret_cast<uintptr_t>(static_cast<const "
<< baseClass->qualifiedCppName() << " *>(class_ptr)) - base";
@@ -4148,255 +4097,203 @@ QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass
result.append(offset);
}
- for (const AbstractMetaClass *baseClass : baseClases)
+ for (const auto &baseClass : baseClases)
result.append(getAncestorMultipleInheritance(baseClass));
}
return result;
}
-void CppGenerator::writeMultipleInheritanceInitializerFunction(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeMultipleInheritanceInitializerFunction(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass)
{
QString className = metaClass->qualifiedCppName();
const QStringList ancestors = getAncestorMultipleInheritance(metaClass);
- s << "static int mi_offsets[] = { ";
- for (int i = 0; i < ancestors.size(); i++)
- s << "-1, ";
- s << "-1 };\n"
- << "int *\n"
+ s << "int *\n"
<< multipleInheritanceInitializerFunctionName(metaClass) << "(const void *cptr)\n"
- << "{\n" << indent
- << "if (mi_offsets[0] == -1) {\n";
- {
- Indentation indent(s);
- s << "std::set<int> offsets;\n"
- << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);\n"
- << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);\n";
-
- for (const QString &ancestor : ancestors)
- s << "offsets.insert(int(" << ancestor << "));\n";
-
- s << "\noffsets.erase(0);\n\n"
- << "std::copy(offsets.cbegin(), offsets.cend(), mi_offsets);\n";
- }
- s << "}\nreturn mi_offsets;\n" << outdent << "}\n";
-}
-
-void CppGenerator::writeSpecialCastFunction(TextStream &s, const AbstractMetaClass *metaClass)
+ << "{\n" << indent;
+ s << "static int mi_offsets[] = {-2";
+ for (qsizetype i = 0; i < ancestors.size(); i++)
+ s << ", 0";
+ s << "};\n"
+ << "if (mi_offsets[0] == -2) {\n" << indent
+ << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);\n"
+ << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);\n"
+ << "int *p = mi_offsets;\n";
+
+ for (const QString &ancestor : ancestors)
+ s << "*p++ = int(" << ancestor << ");\n";
+ s << "std::sort(mi_offsets, p);\n"
+ << "auto *end = std::unique(mi_offsets, p);\n"
+ << "*end++ = -1;\n"
+ << "if (mi_offsets[0] == 0)\n"
+ << indent
+ << "std::memmove(&mi_offsets[0], &mi_offsets[1], (end - mi_offsets - 1) * sizeof(int));\n"
+ << outdent << outdent
+ << "}\nreturn mi_offsets;\n" << outdent << "}\n";
+}
+
+void CppGenerator::writeSpecialCastFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
QString className = metaClass->qualifiedCppName();
s << "static void * " << cpythonSpecialCastFunctionName(metaClass)
<< "(void *obj, PyTypeObject *desiredType)\n{\n" << indent
- << "auto me = reinterpret_cast< ::" << className << " *>(obj);\n";
+ << "auto me = reinterpret_cast< " << m_gsp << className << " *>(obj);\n";
bool firstClass = true;
const auto &allAncestors = metaClass->allTypeSystemAncestors();
- for (const AbstractMetaClass *baseClass : allAncestors) {
+ for (const auto &baseClass : allAncestors) {
if (!firstClass)
s << "else ";
- s << "if (desiredType == " << cpythonTypeNameExt(baseClass->typeEntry()) << ")\n";
- Indentation indent(s);
- s << "return static_cast< ::" << baseClass->qualifiedCppName() << " *>(me);\n";
+ s << "if (desiredType == " << cpythonTypeNameExt(baseClass->typeEntry())
+ << ")\n" << indent
+ << "return static_cast< " << getFullTypeName(baseClass) << " *>(me);\n"
+ << outdent;
firstClass = false;
}
s << "return me;\n" << outdent << "}\n\n";
}
void CppGenerator::writePrimitiveConverterInitialization(TextStream &s,
- const CustomConversion *customConversion)
+ const CustomConversionPtr &customConversion)
{
- const TypeEntry *type = customConversion->ownerType();
+ TypeEntryCPtr type = customConversion->ownerType();
QString converter = converterObject(type);
s << "// Register converter for type '" << type->qualifiedTargetLangName() << "'.\n"
<< converter << " = Shiboken::Conversions::createConverter(";
if (!type->hasTargetLangApiType())
s << "nullptr";
- else if (type->targetLangApiName() == cPyObjectT())
+ else if (type->targetLangApiName() == cPyObjectT)
s << "&PyBaseObject_Type";
else
s << '&' << type->targetLangApiName() << "_Type";
QString typeName = fixedCppTypeName(type);
s << ", " << cppToPythonFunctionName(typeName, typeName) << ");\n"
- << "Shiboken::Conversions::registerConverterName(" << converter << ", \""
- << type->qualifiedCppName() << "\");\n";
+ << registerConverterName(type->qualifiedCppName(), converter);
writeCustomConverterRegister(s, customConversion, converter);
}
-void CppGenerator::writeEnumConverterInitialization(TextStream &s, const AbstractMetaEnum &metaEnum)
+static void registerConverterInScopes(TextStream &s, QStringView signature,
+ QAnyStringView varName = converterVar)
{
- if (metaEnum.isPrivate() || metaEnum.isAnonymous())
- return;
- writeEnumConverterInitialization(s, metaEnum.typeEntry());
+ while (true) {
+ s << registerConverterName(signature, varName);
+ const auto qualifierPos = signature.indexOf("::"_L1);
+ if (qualifierPos == -1)
+ break;
+ signature = signature.sliced(qualifierPos + 2);
+ }
}
-void CppGenerator::writeEnumConverterInitialization(TextStream &s, const TypeEntry *enumType)
+void CppGenerator::writeEnumConverterInitialization(TextStream &s, const AbstractMetaEnum &metaEnum)
{
- if (!enumType)
+ if (metaEnum.isPrivate() || metaEnum.isAnonymous())
return;
- QString enumFlagName = enumType->isFlags() ? u"flag"_s : u"enum"_s;
- QString enumPythonVar = enumType->isFlags() ? u"FType"_s : u"EType"_s;
-
- const FlagsTypeEntry *flags = nullptr;
- if (enumType->isFlags())
- flags = static_cast<const FlagsTypeEntry *>(enumType);
+ EnumTypeEntryCPtr enumType = metaEnum.typeEntry();
+ Q_ASSERT(enumType);
- s << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName()
- << "'.\n{\n";
- {
- Indentation indent(s);
- QString typeName = fixedCppTypeName(enumType);
- s << "SbkConverter *converter = Shiboken::Conversions::createConverter("
- << enumPythonVar << ',' << '\n';
- {
- Indentation indent(s);
- s << cppToPythonFunctionName(typeName, typeName) << ");\n";
- }
+ static const char enumPythonVar[] = "EType";
- if (flags) {
- QString enumTypeName = fixedCppTypeName(flags->originator());
- QString toCpp = pythonToCppFunctionName(enumTypeName, typeName);
- QString isConv = convertibleToCppFunctionName(enumTypeName, typeName);
- writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
- }
+ s << "// Register converter for enum '" << enumType->qualifiedCppName()
+ << "'.\n{\n" << indent;
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
+ const QString typeName = fixedCppTypeName(enumType);
+ s << "SbkConverter *converter = Shiboken::Conversions::createConverter("
+ << enumPythonVar << ',' << '\n' << indent
+ << cppToPythonFunctionName(typeName, typeName) << ");\n" << outdent;
- if (flags) {
- QString toCpp = pythonToCppFunctionName(u"number"_s, typeName);
- QString isConv = convertibleToCppFunctionName(u"number"_s, typeName);
- writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
- }
-
- s << "Shiboken::Enum::setTypeConverter(" << enumPythonVar
- << ", converter, " << (enumType->isFlags() ? "true" : "false") << ");\n";
-
- QString signature = enumType->qualifiedCppName();
- // Replace "QFlags<Class::Option>" by "Class::Options"
- if (flags && signature.startsWith(u"QFlags<") && signature.endsWith(u'>')) {
- signature.chop(1);
- signature.remove(0, 7);
- const int lastQualifierPos = signature.lastIndexOf(u"::");
- if (lastQualifierPos != -1) {
- signature.replace(lastQualifierPos + 2, signature.size() - lastQualifierPos - 2,
- flags->flagsName());
- } else {
- signature = flags->flagsName();
- }
- }
-
- while (true) {
- s << "Shiboken::Conversions::registerConverterName(converter, \""
- << signature << "\");\n";
- const int qualifierPos = signature.indexOf(u"::");
- if (qualifierPos != -1)
- signature.remove(0, qualifierPos + 2);
- else
- break;
- }
- if (flags) {
- // PYSIDE-1673: Also register "QFlags<Class::Option>" purely for
- // the purpose of finding the converter by QVariant::typeName()
- // in the QVariant conversion code.
- s << "Shiboken::Conversions::registerConverterName(converter, \""
- << flags->name() << "\");\n";
- }
+ const QString toCpp = pythonToCppFunctionName(typeName, typeName);
+ const QString isConv = convertibleToCppFunctionName(typeName, typeName);
+ writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
+ s << "Shiboken::Enum::setTypeConverter(" << enumPythonVar
+ << ", converter);\n";
- }
- s << "}\n";
+ registerConverterInScopes(s, enumType->qualifiedCppName());
+ if (auto flags = enumType->flags())
+ s << "// Register converter for flag '" << flags->qualifiedCppName() << "'.\n"
+ << registerConverterName(flags->name()) // QMetaType
+ << registerConverterName(flags->originalName()); // Signals with flags
- if (!flags)
- writeEnumConverterInitialization(s, static_cast<const EnumTypeEntry *>(enumType)->flags());
+ s << outdent << "}\n";
}
-QString CppGenerator::writeContainerConverterInitialization(TextStream &s, const AbstractMetaType &type) const
+QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
+ const AbstractMetaType &type,
+ const ApiExtractorResult &api)
{
- QByteArray cppSignature = QMetaObject::normalizedSignature(type.cppSignature().toUtf8());
+ const auto cppSignature =
+ QString::fromUtf8(QMetaObject::normalizedSignature(type.cppSignature().toUtf8()));
s << "// Register converter for type '" << cppSignature << "'.\n";
- QString converter = converterObject(type);
+ const QString converter = converterObject(type);
s << converter << " = Shiboken::Conversions::createConverter(";
- if (type.typeEntry()->targetLangApiName() == cPyObjectT()) {
+
+ Q_ASSERT(type.typeEntry()->isContainer());
+ const auto typeEntry = std::static_pointer_cast<const ContainerTypeEntry>(type.typeEntry());
+
+ const QString targetTypeName = containerNativeToTargetTypeName(typeEntry);
+ if (targetTypeName == cPyObjectT) {
s << "&PyBaseObject_Type";
} else {
- QString baseName = cpythonBaseName(type.typeEntry());
- if (baseName == cPySequenceT())
- baseName = cPyListT();
- s << '&' << baseName << "_Type";
+ s << '&' << targetTypeName << "_Type";
}
- QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, typeName) << ");\n";
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- s << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");\n";
- if (usePySideExtensions() && cppSignature.startsWith("const ") && cppSignature.endsWith("&")) {
- cppSignature.chop(1);
- cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1);
- s << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");\n";
- }
- const QString converterObj = converterObject(type);
- writeAddPythonToCppConversion(s, converterObj, toCpp, isConv);
- return converterObj;
-}
-
-void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s, const AbstractMetaType &type) const
-{
- const QByteArray cppSignature = type.cppSignature().toUtf8();
- auto writeConversionRegister = [&s](const AbstractMetaType &sourceType, const QString &targetTypeName, const QString &targetConverter)
- {
- const QString sourceTypeName = fixedCppTypeName(sourceType);
- const QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
- const QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
- };
-
- const auto classes = findSmartPointeeBaseClasses(api(), type);
- if (classes.isEmpty())
- return;
+ const QString typeName = fixedCppTypeName(type);
+ s << ", " << cppToPythonFunctionName(typeName, targetTypeName) << ");\n";
- auto *smartPointerTypeEntry = static_cast<const SmartPointerTypeEntry *>(type.typeEntry());
+ s << registerConverterName(cppSignature, converter);
+ if (usePySideExtensions() && cppSignature.startsWith("const "_L1)
+ && cppSignature.endsWith(u'&')) {
+ auto underlyingType = QStringView{cppSignature}.sliced(6, cppSignature.size() - 7);
+ s << registerConverterName(underlyingType, converter);
+ }
- s << "// Register SmartPointer converter for type '" << cppSignature << "'." << '\n'
- << "///////////////////////////////////////////////////////////////////////////////////////\n\n";
+ for (const auto &conv : typeEntry->customConversion()->targetToNativeConversions()) {
+ const QString &sourceTypeName = conv.sourceTypeName();
+ QString toCpp = pythonToCppFunctionName(sourceTypeName, typeName);
+ QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName);
+ writeAddPythonToCppConversion(s, converter, toCpp, isConv);
+ }
- for (auto *base : classes) {
- auto *baseTe = base->typeEntry();
- if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
- const auto smartTargetType = opt.value();
- s << "// Convert to SmartPointer derived class: ["
- << smartTargetType.cppSignature() << "]\n";
- const QString converter = u"Shiboken::Conversions::getConverter(\""_s
- + smartTargetType.cppSignature() + u"\")"_s;
- writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter);
- } else {
- s << "// Class not found:" << type.instantiations().at(0).cppSignature();
+ auto typedefItPair = api.typedefTargetToName().equal_range(type.cppSignature());
+ if (typedefItPair.first != typedefItPair.second) {
+ auto *typeDb = TypeDatabase::instance();
+ s << "// Register converters for type aliases of " << cppSignature << "'.\n";
+ for (auto it = typedefItPair.first; it != typedefItPair.second; ++it) {
+ if (!typeDb->findType(it.value()))
+ s << registerConverterName(it.value(), converter);
}
}
- s << "///////////////////////////////////////////////////////////////////////////////////////" << '\n' << '\n';
+ return converter;
}
-void CppGenerator::writeExtendedConverterInitialization(TextStream &s, const TypeEntry *externalType,
+QString CppGenerator::typeInitStruct(const TypeEntryCPtr &te)
+{
+ return cppApiVariableName(te->targetLangPackage()) + u'['
+ + getTypeIndexVariableName(te) + u']';
+}
+
+void CppGenerator::writeExtendedConverterInitialization(TextStream &s,
+ const TypeEntryCPtr &externalType,
const AbstractMetaClassCList &conversions)
{
s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName()
<< ".\n";
- for (const AbstractMetaClass *sourceClass : conversions) {
- const QString converterVar = cppApiVariableName(externalType->targetLangPackage()) + u'['
- + getTypeIndexVariableName(externalType) + u']';
+ for (const auto &sourceClass : conversions) {
QString sourceTypeName = fixedCppTypeName(sourceClass->typeEntry());
QString targetTypeName = fixedCppTypeName(externalType);
QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
+ if (!externalType->isPrimitive())
+ s << cpythonTypeNameExt(externalType) << ";\n";
+ writeAddPythonToCppConversion(s, typeInitStruct(externalType), toCpp, isConv);
}
}
-QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass *metaClass)
+QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass->typeEntry()) + u"_mi_init"_s;
}
-bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass *metaClass)
+bool CppGenerator::supportsMappingProtocol(const AbstractMetaClassCPtr &metaClass)
{
for (const auto &m : mappingProtocols()) {
if (metaClass->hasFunction(m.name))
@@ -4406,7 +4303,7 @@ bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass *metaClass)
return false;
}
-bool CppGenerator::supportsNumberProtocol(const AbstractMetaClass *metaClass) const
+bool CppGenerator::supportsNumberProtocol(const AbstractMetaClassCPtr &metaClass)
{
return metaClass->hasArithmeticOperatorOverload()
|| metaClass->hasIncDecrementOperatorOverload()
@@ -4415,18 +4312,18 @@ bool CppGenerator::supportsNumberProtocol(const AbstractMetaClass *metaClass) co
|| hasBoolCast(metaClass);
}
-bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass *metaClass)
+bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClassCPtr &metaClass)
{
for (const auto &seq : sequenceProtocols()) {
if (metaClass->hasFunction(seq.name))
return true;
}
- const ComplexTypeEntry *baseType = metaClass->typeEntry()->baseContainerType();
+ ComplexTypeEntryCPtr baseType = metaClass->typeEntry()->baseContainerType();
return baseType && baseType->isContainer();
}
-bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass *metaClass) const
+bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClassCPtr &metaClass)
{
for (const AbstractMetaField &f : metaClass->fields()) {
if (!f.isStatic())
@@ -4444,29 +4341,24 @@ bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass *metaClass)
struct pyTypeSlotEntry
{
- explicit pyTypeSlotEntry(const char *name, const QString &function) :
+ explicit pyTypeSlotEntry(QAnyStringView name, QAnyStringView function) :
m_name(name), m_function(function) {}
- const char *m_name;
- const QString &m_function;
+ QAnyStringView m_name;
+ QAnyStringView m_function;
};
TextStream &operator<<(TextStream &str, const pyTypeSlotEntry &e)
{
- str << '{' << e.m_name << ',';
- const int padding = qMax(0, 18 - int(strlen(e.m_name)));
- for (int p = 0; p < padding; ++p)
- str << ' ';
- if (e.m_function.isEmpty())
- str << NULL_PTR;
- else
- str << "reinterpret_cast<void *>(" << e.m_function << ')';
- str << "},\n";
+ if (!e.m_function.isEmpty()) {
+ str << '{' << e.m_name << ',' << Pad(' ', qMax(0, 18 - e.m_name.size()))
+ << "reinterpret_cast<void *>(" << e.m_function << ")},\n";
+ }
return str;
}
void CppGenerator::writeClassDefinition(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext)
{
QString tp_init;
@@ -4475,7 +4367,6 @@ void CppGenerator::writeClassDefinition(TextStream &s,
QString tp_hash;
QString tp_call;
const QString className = chopType(cpythonTypeName(metaClass));
- QString baseClassName;
AbstractMetaFunctionCList ctors;
const auto &allCtors = metaClass->queryFunctions(FunctionQueryOption::AnyConstructor);
for (const auto &f : allCtors) {
@@ -4485,13 +4376,10 @@ void CppGenerator::writeClassDefinition(TextStream &s,
}
}
- if (!metaClass->baseClass())
- baseClassName = u"SbkObject_TypeF()"_s;
-
bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor();
const bool isQApp = usePySideExtensions()
- && metaClass->inheritsFrom(u"QCoreApplication"_s);
+ && inheritsFrom(metaClass, u"QCoreApplication"_s);
QString tp_flags = u"Py_TPFLAGS_DEFAULT"_s;
if (!metaClass->attributes().testFlag(AbstractMetaClass::FinalCppClass))
@@ -4543,25 +4431,31 @@ void CppGenerator::writeClassDefinition(TextStream &s,
if (generateRichComparison(classContext))
tp_richcompare = cpythonBaseName(metaClass) + u"_richcompare"_s;
+ const bool isSmartPointer = classContext.forSmartPointer();
QString tp_getset;
- if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer())
+ if (shouldGenerateGetSetList(metaClass) && !isSmartPointer)
tp_getset = cpythonGettersSettersDefinitionName(metaClass);
// search for special functions
clearTpFuncs();
for (const auto &func : metaClass->functions()) {
- if (m_tpFuncs.contains(func->name()))
- m_tpFuncs[func->name()] = cpythonFunctionName(func);
+ // Special non-operator functions identified by name
+ auto it = m_tpFuncs.find(func->name());
+ if (it != m_tpFuncs.end())
+ it.value() = cpythonFunctionName(func);
+ else if ( it = m_nbFuncs.find(func->name()); it != m_nbFuncs.end() )
+ it.value() = cpythonFunctionName(func);
}
- if (m_tpFuncs.value(reprFunction()).isEmpty()
- && metaClass->hasToStringCapability()) {
- m_tpFuncs[reprFunction()] = writeReprFunction(s,
- classContext,
- metaClass->toStringCapabilityIndirections());
+ if (m_tpFuncs.value(REPR_FUNCTION).isEmpty()
+ && (isSmartPointer || metaClass->hasToStringCapability())) {
+ const QString name = isSmartPointer
+ ? writeSmartPointerReprFunction(s, classContext)
+ : writeReprFunction(s, classContext, metaClass->toStringCapabilityIndirections());
+ m_tpFuncs[REPR_FUNCTION] = name;
}
// class or some ancestor has multiple inheritance
- const AbstractMetaClass *miClass = getMultipleInheritingClass(metaClass);
+ const auto miClass = getMultipleInheritingClass(metaClass);
if (miClass) {
if (metaClass == miClass)
writeMultipleInheritanceInitializerFunction(s, metaClass);
@@ -4575,8 +4469,8 @@ void CppGenerator::writeClassDefinition(TextStream &s,
if (hasHashFunction(metaClass))
tp_hash = u'&' + cpythonBaseName(metaClass) + u"_HashFunc"_s;
- const auto callOp = metaClass->findFunction(u"operator()");
- if (!callOp.isNull() && !callOp->isModifiedRemoved())
+ const auto callOp = metaClass->findFunction("operator()");
+ if (callOp && !callOp->isModifiedRemoved())
tp_call = u'&' + cpythonFunctionName(callOp);
const QString typePtr = u"_"_s + className
@@ -4587,7 +4481,7 @@ void CppGenerator::writeClassDefinition(TextStream &s,
<< "}\n\nstatic PyType_Slot " << className << "_slots[] = {\n" << indent
<< "{Py_tp_base, nullptr}, // inserted by introduceWrapperType\n"
<< pyTypeSlotEntry("Py_tp_dealloc", tp_dealloc)
- << pyTypeSlotEntry("Py_tp_repr", m_tpFuncs.value(reprFunction()))
+ << pyTypeSlotEntry("Py_tp_repr", m_tpFuncs.value(REPR_FUNCTION))
<< pyTypeSlotEntry("Py_tp_hash", tp_hash)
<< pyTypeSlotEntry("Py_tp_call", tp_call)
<< pyTypeSlotEntry("Py_tp_str", m_tpFuncs.value(u"__str__"_s))
@@ -4611,7 +4505,6 @@ void CppGenerator::writeClassDefinition(TextStream &s,
writeTypeAsMappingDefinition(s, metaClass);
}
if (supportsNumberProtocol(metaClass)) {
- // This one must come last. See the function itself.
s << "// type supports number protocol\n";
writeTypeAsNumberDefinition(s, metaClass);
}
@@ -4626,12 +4519,12 @@ void CppGenerator::writeClassDefinition(TextStream &s,
}
void CppGenerator::writeMappingMethods(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &context) const
{
for (const auto & m : mappingProtocols()) {
const auto func = metaClass->findFunction(m.name);
- if (func.isNull())
+ if (!func)
continue;
QString funcName = cpythonFunctionName(func);
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
@@ -4648,14 +4541,14 @@ void CppGenerator::writeMappingMethods(TextStream &s,
}
void CppGenerator::writeSequenceMethods(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &context) const
{
bool injectedCode = false;
for (const auto &seq : sequenceProtocols()) {
const auto func = metaClass->findFunction(seq.name);
- if (func.isNull())
+ if (!func)
continue;
injectedCode = true;
QString funcName = cpythonFunctionName(func);
@@ -4679,25 +4572,25 @@ void CppGenerator::writeSequenceMethods(TextStream &s,
static const QHash<QString, QString> &sqFuncs()
{
static const QHash<QString, QString> result = {
- {u"__concat__"_s, u"sq_concat"_s},
- {u"__contains__"_s, u"sq_contains"_s},
- {u"__getitem__"_s, u"sq_item"_s},
- {u"__getslice__"_s, u"sq_slice"_s},
- {u"__len__"_s, u"sq_length"_s},
- {u"__setitem__"_s, u"sq_ass_item"_s},
- {u"__setslice__"_s, u"sq_ass_slice"_s}
+ {u"__concat__"_s, u"Py_sq_concat"_s},
+ {u"__contains__"_s, u"Py_sq_contains"_s},
+ {u"__getitem__"_s, u"Py_sq_item"_s},
+ {u"__getslice__"_s, u"Py_sq_slice"_s},
+ {u"__len__"_s, u"Py_sq_length"_s},
+ {u"__setitem__"_s, u"Py_sq_ass_item"_s},
+ {u"__setslice__"_s, u"Py_sq_ass_slice"_s}
};
return result;
}
void CppGenerator::writeTypeAsSequenceDefinition(TextStream &s,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
bool hasFunctions = false;
QMap<QString, QString> funcs;
for (const auto &seq : sequenceProtocols()) {
const auto func = metaClass->findFunction(seq.name);
- if (!func.isNull()) {
+ if (func) {
funcs.insert(seq.name, u'&' + cpythonFunctionName(func));
hasFunctions = true;
}
@@ -4715,38 +4608,34 @@ void CppGenerator::writeTypeAsSequenceDefinition(TextStream &s,
for (auto it = sqFuncs().cbegin(), end = sqFuncs().cend(); it != end; ++it) {
const QString &sqName = it.key();
auto fit = funcs.constFind(sqName);
- if (fit != funcs.constEnd()) {
- s << "{Py_" << it.value() << ", reinterpret_cast<void *>("
- << fit.value() << ")},\n";
- }
+ if (fit != funcs.constEnd())
+ s << pyTypeSlotEntry(it.value(), fit.value());
}
}
void CppGenerator::writeTypeAsMappingDefinition(TextStream &s,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
// Sequence protocol structure members names
static const QHash<QString, QString> mpFuncs{
- {u"__mlen__"_s, u"mp_length"_s},
- {u"__mgetitem__"_s, u"mp_subscript"_s},
- {u"__msetitem__"_s, u"mp_ass_subscript"_s},
+ {u"__mlen__"_s, u"Py_mp_length"_s},
+ {u"__mgetitem__"_s, u"Py_mp_subscript"_s},
+ {u"__msetitem__"_s, u"Py_mp_ass_subscript"_s},
};
QMap<QString, QString> funcs;
for (const auto &m : mappingProtocols()) {
const auto func = metaClass->findFunction(m.name);
- if (!func.isNull()) {
+ if (func) {
const QString entry = u"reinterpret_cast<void *>(&"_s
+ cpythonFunctionName(func) + u')';
funcs.insert(m.name, entry);
- } else {
- funcs.insert(m.name, NULL_PTR);
}
}
for (auto it = mpFuncs.cbegin(), end = mpFuncs.cend(); it != end; ++it) {
const auto fit = funcs.constFind(it.key());
if (fit != funcs.constEnd())
- s << "{Py_" << it.value() << ", " << fit.value() << "},\n";
+ s << pyTypeSlotEntry(it.value(), fit.value());
}
}
@@ -4754,105 +4643,102 @@ void CppGenerator::writeTypeAsMappingDefinition(TextStream &s,
static const QHash<QString, QString> &nbFuncs()
{
static const QHash<QString, QString> result = {
- {u"__add__"_s, u"nb_add"_s},
- {u"__sub__"_s, u"nb_subtract"_s},
- {u"__mul__"_s, u"nb_multiply"_s},
- {u"__div__"_s, u"nb_divide"_s},
- {u"__mod__"_s, u"nb_remainder"_s},
- {u"__neg__"_s, u"nb_negative"_s},
- {u"__pos__"_s, u"nb_positive"_s},
- {u"__invert__"_s, u"nb_invert"_s},
- {u"__lshift__"_s, u"nb_lshift"_s},
- {u"__rshift__"_s, u"nb_rshift"_s},
- {u"__and__"_s, u"nb_and"_s},
- {u"__xor__"_s, u"nb_xor"_s},
- {u"__or__"_s, u"nb_or"_s},
- {u"__iadd__"_s, u"nb_inplace_add"_s},
- {u"__isub__"_s, u"nb_inplace_subtract"_s},
- {u"__imul__"_s, u"nb_inplace_multiply"_s},
- {u"__idiv__"_s, u"nb_inplace_divide"_s},
- {u"__imod__"_s, u"nb_inplace_remainder"_s},
- {u"__ilshift__"_s, u"nb_inplace_lshift"_s},
- {u"__irshift__"_s, u"nb_inplace_rshift"_s},
- {u"__iand__"_s, u"nb_inplace_and"_s},
- {u"__ixor__"_s, u"nb_inplace_xor"_s},
- {u"__ior__"_s, u"nb_inplace_or"_s},
- {boolT(), u"nb_nonzero"_s}
+ {u"__abs__"_s, u"Py_nb_absolute"_s},
+ {u"__add__"_s, u"Py_nb_add"_s},
+ {u"__sub__"_s, u"Py_nb_subtract"_s},
+ {u"__mul__"_s, u"Py_nb_multiply"_s},
+ {u"__div__"_s, u"Py_nb_true_divide"_s},
+ {u"__mod__"_s, u"Py_nb_remainder"_s},
+ {u"__neg__"_s, u"Py_nb_negative"_s},
+ {u"__pos__"_s, u"Py_nb_positive"_s},
+ {u"__pow__"_s, u"Py_nb_power"_s},
+ {u"__invert__"_s, u"Py_nb_invert"_s},
+ {u"__lshift__"_s, u"Py_nb_lshift"_s},
+ {u"__rshift__"_s, u"Py_nb_rshift"_s},
+ {u"__and__"_s, u"Py_nb_and"_s},
+ {u"__xor__"_s, u"Py_nb_xor"_s},
+ {u"__or__"_s, u"Py_nb_or"_s},
+ {u"__iadd__"_s, u"Py_nb_inplace_add"_s},
+ {u"__isub__"_s, u"Py_nb_inplace_subtract"_s},
+ {u"__imul__"_s, u"Py_nb_inplace_multiply"_s},
+ {u"__imod__"_s, u"Py_nb_inplace_remainder"_s},
+ {u"__ilshift__"_s, u"Py_nb_inplace_lshift"_s},
+ {u"__irshift__"_s, u"Py_nb_inplace_rshift"_s},
+ {u"__iand__"_s, u"Py_nb_inplace_and"_s},
+ {u"__ixor__"_s, u"Py_nb_inplace_xor"_s},
+ {u"__ior__"_s, u"Py_nb_inplace_or"_s},
+ {u"__bool__"_s, u"Py_nb_bool"_s},
+ {u"__int__"_s, u"Py_nb_int"_s},
+ {u"__float__"_s, u"Py_nb_float"_s}
};
return result;
}
-void CppGenerator::writeTypeAsNumberDefinition(TextStream &s, const AbstractMetaClass *metaClass) const
+void CppGenerator::writeTypeAsNumberDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass) const
{
QMap<QString, QString> nb;
- const QList<AbstractMetaFunctionCList> opOverloads =
- filterGroupedOperatorFunctions(metaClass,
- OperatorQueryOption::ArithmeticOp
- | OperatorQueryOption::IncDecrementOp
- | OperatorQueryOption::LogicalOp
- | OperatorQueryOption::BitwiseOp);
-
- for (const AbstractMetaFunctionCList &opOverload : opOverloads) {
+ const QList<AbstractMetaFunctionCList> opOverloads = numberProtocolOperators(metaClass);
+ for (const auto &opOverload : opOverloads) {
const auto rfunc = opOverload.at(0);
QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc);
nb[opName] = cpythonFunctionName(rfunc);
}
+ for (auto it = m_nbFuncs.cbegin(), end = m_nbFuncs.cend(); it != end; ++it) {
+ if (!it.value().isEmpty())
+ nb.insert(it.key(), it.value());
+ }
+
QString baseName = cpythonBaseName(metaClass);
if (hasBoolCast(metaClass))
- nb.insert(boolT(), baseName + u"___nb_bool"_s);
+ nb.insert(u"__bool__"_s, baseName + u"___nb_bool"_s);
for (auto it = nbFuncs().cbegin(), end = nbFuncs().cend(); it != end; ++it) {
const QString &nbName = it.key();
- if (nbName == u"__div__" || nbName == u"__idiv__")
- continue; // excludeFromPy3K
const auto nbIt = nb.constFind(nbName);
- if (nbIt != nb.constEnd()) {
- const QString fixednbName = nbName == boolT()
- ? u"nb_bool"_s : it.value();
- s << "{Py_" << fixednbName << ", reinterpret_cast<void *>("
- << nbIt.value() << ")},\n";
- }
- }
-
- auto nbIt = nb.constFind(u"__div__"_s);
- if (nbIt != nb.constEnd())
- s << "{Py_nb_true_divide, reinterpret_cast<void *>(" << nbIt.value() << ")},\n";
-
- nbIt = nb.constFind(u"__idiv__"_s);
- if (nbIt != nb.constEnd()) {
- s << "// This function is unused in Python 3. We reference it here.\n"
- << "{0, reinterpret_cast<void *>(" << nbIt.value() << ")},\n"
- << "// This list is ending at the first 0 entry.\n"
- << "// Therefore, we need to put the unused functions at the very end.\n";
+ if (nbIt != nb.constEnd())
+ s << pyTypeSlotEntry(it.value(), nbIt.value());
}
}
-void CppGenerator::writeTpTraverseFunction(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeTpTraverseFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
QString baseName = cpythonBaseName(metaClass);
s << "static int " << baseName
<< "_traverse(PyObject *self, visitproc visit, void *arg)\n{\n" << indent
- << "return SbkObject_TypeF()->tp_traverse(self, visit, arg);\n"
+ << "auto traverseProc = "
+ << pyTypeGetSlot("traverseproc", sbkObjectTypeF, "Py_tp_traverse") << ";\n"
+ << "return traverseProc(self, visit, arg);\n"
<< outdent << "}\n";
}
-void CppGenerator::writeTpClearFunction(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeTpClearFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
QString baseName = cpythonBaseName(metaClass);
s << "static int " << baseName << "_clear(PyObject *self)\n{\n" << indent
- << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_clear(self);\n"
+ << "auto clearProc = "
+ << pyTypeGetSlot("inquiry", sbkObjectTypeF, "Py_tp_clear") << ";\n"
+ << "return clearProc(self);\n"
<< outdent << "}\n";
}
-void CppGenerator::writeCopyFunction(TextStream &s, const GeneratorContext &context) const
+QString CppGenerator::writeCopyFunction(TextStream &s,
+ TextStream &definitionStream,
+ TextStream &signatureStream,
+ const GeneratorContext &context)
{
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
const QString className = chopType(cpythonTypeName(metaClass));
- s << "static PyObject *" << className << "___copy__(PyObject *self)\n"
- << "{\n" << indent;
+ const QString funcName = className + u"__copy__"_s;
+
+ signatureStream << fullPythonClassName(metaClass) << ".__copy__()\n";
+ definitionStream << PyMethodDefEntry{u"__copy__"_s, funcName, {"METH_NOARGS"_ba}, {}}
+ << ",\n";
+
+ s << "static PyObject *" << funcName << "(PyObject *self)\n"
+ << "{\n" << indent;
writeCppSelfDefinition(s, context, ErrorReturn::Default, CppSelfDefinitionFlag::CppSelfAsReference);
QString conversionCode;
if (!context.forSmartPointer())
@@ -4865,16 +4751,18 @@ void CppGenerator::writeCopyFunction(TextStream &s, const GeneratorContext &cont
writeFunctionReturnErrorCheckSection(s, ErrorReturn::Default);
s << "return " << PYTHON_RETURN_VAR << ";\n" << outdent
<< "}\n\n";
+
+ return funcName;
}
static inline void writeGetterFunctionStart(TextStream &s, const QString &funcName)
{
- s << "static PyObject *" << funcName << "(PyObject *self, void *)\n"
+ s << "static PyObject *" << funcName << "(PyObject *self, void * /* closure */)\n"
<< "{\n" << indent;
}
QString CppGenerator::cppFieldAccess(const AbstractMetaField &metaField,
- const GeneratorContext &context) const
+ const GeneratorContext &context)
{
QString result;
QTextStream str(&result);
@@ -4888,7 +4776,7 @@ QString CppGenerator::cppFieldAccess(const AbstractMetaField &metaField,
void CppGenerator::writeGetterFunction(TextStream &s,
const AbstractMetaField &metaField,
- const GeneratorContext &context) const
+ const GeneratorContext &context)
{
writeGetterFunctionStart(s, cpythonGetterFunctionName(metaField));
@@ -4925,34 +4813,31 @@ void CppGenerator::writeGetterFunction(TextStream &s,
if (newWrapperSameObject) {
// Special case colocated field with same address (first field in a struct)
s << "if (reinterpret_cast<void *>("
- << cppField
- << ") == reinterpret_cast<void *>("
- << CPP_SELF_VAR << ")) {\n";
- {
- Indentation indent(s);
- s << "pyOut = reinterpret_cast<PyObject *>(Shiboken::Object::findColocatedChild("
- << "reinterpret_cast<SbkObject *>(self), "
- << cpythonTypeNameExt(fieldType)
- << "));\n";
- s << "if (pyOut) {\n";
- {
- Indentation indent(s);
- s << "Py_IncRef(pyOut);\n"
- << "return pyOut;\n";
- }
- s << "}\n";
- }
+ << cppField << ") == reinterpret_cast<void *>("
+ << CPP_SELF_VAR << ")) {\n" << indent
+ << "pyOut = reinterpret_cast<PyObject *>(Shiboken::Object::findColocatedChild("
+ << "reinterpret_cast<SbkObject *>(self), "
+ << cpythonTypeNameExt(fieldType) << "));\n"
+ << "if (pyOut != nullptr) {\n" << indent
+ << "Py_IncRef(pyOut);\n"
+ << "return pyOut;\n"
+ << outdent << "}\n";
// Check if field wrapper has already been created.
- s << "} else if (Shiboken::BindingManager::instance().hasWrapper(" << cppField << ")) {" << "\n";
- {
- Indentation indent(s);
- s << "pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper("
- << cppField << "));" << "\n"
- << "Py_IncRef(pyOut);" << "\n"
- << "return pyOut;" << "\n";
- }
- s << "}\n";
- // Create and register new wrapper
+ s << outdent << "} else if (Shiboken::BindingManager::instance().hasWrapper("
+ << cppField << ")) {" << "\n" << indent
+ << "pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper("
+ << cppField << "));" << "\n"
+ << "Py_IncRef(pyOut);" << "\n"
+ << "return pyOut;" << "\n"
+ << outdent << "}\n";
+ // Create and register new wrapper. We force a pointer conversion also
+ // for wrapped value types so that they refer to the struct member,
+ // avoiding any trouble copying them. Add a parent relationship to
+ // properly notify if the struct is deleted (see protected_test.py,
+ // testProtectedValueTypeProperty()). Note that this has currently
+ // unsolved issues when using temporary Python lists of structs
+ // which can cause elements to be reported deleted in expressions like
+ // "foo.list_of_structs[2].field".
s << "pyOut = "
<< "Shiboken::Object::newObject(" << cpythonTypeNameExt(fieldType)
<< ", " << cppField << ", false, true);\n"
@@ -4965,30 +4850,29 @@ void CppGenerator::writeGetterFunction(TextStream &s,
}
// Write a getter for QPropertySpec
-void CppGenerator::writeGetterFunction(TextStream &s, const QPropertySpec &property,
- const GeneratorContext &context) const
+void CppGenerator::writeGetterFunction(TextStream &s,
+ const QPropertySpec &property,
+ const GeneratorContext &context)
{
writeGetterFunctionStart(s, cpythonGetterFunctionName(property, context.metaClass()));
writeCppSelfDefinition(s, context);
- const QString value = QStringLiteral("value");
+ const QString value = "value"_L1;
s << "auto " << value << " = " << CPP_SELF_VAR << "->" << property.read() << "();\n"
- << "auto pyResult = ";
+ << "auto *pyResult = ";
writeToPythonConversion(s, property.type(), context.metaClass(), value);
- s << ";\nif (PyErr_Occurred() || !pyResult) {\n";
- {
- Indentation indent(s);
- s << "Py_XDECREF(pyResult);\nreturn {};\n";
- }
- s << "}\nreturn pyResult;\n" << outdent << "}\n\n";
+ s << ";\nif (" << shibokenErrorsOccurred << " || pyResult == nullptr) {\n"
+ << indent << "Py_XDECREF(pyResult);\nreturn {};\n" << outdent
+ << "}\nreturn pyResult;\n" << outdent << "}\n\n";
}
// Write setter function preamble (type checks on "pyIn")
-void CppGenerator::writeSetterFunctionPreamble(TextStream &s, const QString &name,
+void CppGenerator::writeSetterFunctionPreamble(TextStream &s,
+ const QString &name,
const QString &funcName,
const AbstractMetaType &type,
- const GeneratorContext &context) const
+ const GeneratorContext &context)
{
- s << "static int " << funcName << "(PyObject *self, PyObject *pyIn, void *)\n"
+ s << "static int " << funcName << "(PyObject *self, PyObject *pyIn, void * /* closure */)\n"
<< "{\n" << indent;
writeCppSelfDefinition(s, context, ErrorReturn::Zero);
@@ -5010,7 +4894,7 @@ void CppGenerator::writeSetterFunctionPreamble(TextStream &s, const QString &nam
void CppGenerator::writeSetterFunction(TextStream &s,
const AbstractMetaField &metaField,
- const GeneratorContext &context) const
+ const GeneratorContext &context)
{
const AbstractMetaType &fieldType = metaField.type();
writeSetterFunctionPreamble(s, metaField.name(), cpythonSetterFunctionName(metaField),
@@ -5042,278 +4926,138 @@ void CppGenerator::writeSetterFunction(TextStream &s,
}
// Write a setter for QPropertySpec
-void CppGenerator::writeSetterFunction(TextStream &s, const QPropertySpec &property,
- const GeneratorContext &context) const
+void CppGenerator::writeSetterFunction(TextStream &s,
+ const QPropertySpec &property,
+ const GeneratorContext &context)
{
- writeSetterFunctionPreamble(s, property.name(),
+ writeSetterFunctionPreamble(s,
+ property.name(),
cpythonSetterFunctionName(property, context.metaClass()),
property.type(), context);
s << "auto cppOut = " << CPP_SELF_VAR << "->" << property.read() << "();\n"
<< PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);\n"
- << "if (PyErr_Occurred())\n";
- {
- Indentation indent(s);
- s << "return -1;\n";
- }
- s << CPP_SELF_VAR << "->" << property.write() << "(cppOut);\n"
+ << "if (" << shibokenErrorsOccurred << ")\n" << indent
+ << "return -1;\n" << outdent
+ << CPP_SELF_VAR << "->" << property.write() << "(cppOut);\n"
<< "return 0;\n" << outdent << "}\n\n";
}
void CppGenerator::writeRichCompareFunctionHeader(TextStream &s,
const QString &baseName,
- const GeneratorContext &context) const
+ const GeneratorContext &context)
{
s << "static PyObject * ";
s << baseName << "_richcompare(PyObject *self, PyObject *" << PYTHON_ARG
<< ", int op)\n{\n" << indent;
writeCppSelfDefinition(s, context, ErrorReturn::Default, CppSelfDefinitionFlag::CppSelfAsReference);
- writeUnusedVariableCast(s, CPP_SELF_VAR);
- s << "PyObject *" << PYTHON_RETURN_VAR << "{};\n"
- << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n";
- writeUnusedVariableCast(s, PYTHON_TO_CPP_VAR);
- s << '\n';
+ s << sbkUnusedVariableCast(CPP_SELF_VAR)
+ << "PyObject *" << PYTHON_RETURN_VAR << "{};\n"
+ << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n"
+ << sbkUnusedVariableCast(PYTHON_TO_CPP_VAR) << '\n';
}
-static const char richCompareComment[] =
- "// PYSIDE-74: By default, we redirect to object's tp_richcompare (which is `==`, `!=`).\n";
-
void CppGenerator::writeRichCompareFunction(TextStream &s,
const GeneratorContext &context) const
{
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
QString baseName = cpythonBaseName(metaClass);
writeRichCompareFunctionHeader(s, baseName, context);
- s << "switch (op) {\n";
- {
- Indentation indent(s);
- const QList<AbstractMetaFunctionCList> &groupedFuncs =
- filterGroupedOperatorFunctions(metaClass, OperatorQueryOption::ComparisonOp);
- for (const AbstractMetaFunctionCList &overloads : groupedFuncs) {
- const auto rfunc = overloads[0];
-
- const auto op = rfunc->comparisonOperatorType().value();
- s << "case " << AbstractMetaFunction::pythonRichCompareOpCode(op) << ':' << '\n';
-
- Indentation indent(s);
-
- int alternativeNumericTypes = 0;
- for (const auto &func : overloads) {
- if (!func->isStatic() &&
- ShibokenGenerator::isNumber(func->arguments().at(0).type().typeEntry()))
- alternativeNumericTypes++;
- }
+ s << "switch (op) {\n" << indent;
+ const QList<AbstractMetaFunctionCList> &groupedFuncs =
+ filterGroupedOperatorFunctions(metaClass, OperatorQueryOption::ComparisonOp);
+ for (const AbstractMetaFunctionCList &overloads : groupedFuncs) {
+ const auto rfunc = overloads[0];
- bool first = true;
- OverloadData overloadData(overloads, api());
- const OverloadDataList &nextOverloads = overloadData.children();
- for (const auto &od : nextOverloads) {
- const auto func = od->referenceFunction();
- if (func->isStatic())
- continue;
- auto argType = getArgumentType(func, 0);
- if (!first) {
- s << " else ";
- } else {
- first = false;
- }
- s << "if (";
- writeTypeCheck(s, argType, PYTHON_ARG,
- alternativeNumericTypes == 1 || isPyInt(argType));
- s << ") {\n";
- {
- Indentation indent(s);
- s << "// " << func->signature() << '\n';
- writeArgumentConversion(s, argType, CPP_ARG0,
- PYTHON_ARG, ErrorReturn::Default,
- metaClass,
- QString(), func->isUserAdded());
-
- // If the function is user added, use the inject code
- bool generateOperatorCode = true;
- if (func->isUserAdded()) {
- CodeSnipList snips = func->injectedCodeSnips();
- if (!snips.isEmpty()) {
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny,
- TypeSystem::TargetLangCode, func,
- false /* uses PyArgs */, &func->arguments().constLast());
- generateOperatorCode = false;
- }
- }
- if (generateOperatorCode) {
- if (!func->isVoid())
- s << func->type().cppSignature() << " " << CPP_RETURN_VAR << " = ";
- // expression
- if (func->isPointerOperator())
- s << '&';
- s << CPP_SELF_VAR << ' '
- << AbstractMetaFunction::cppComparisonOperator(op) << " (";
- if (auto deRef = argType.shouldDereferenceArgument(); deRef > 0)
- s << QByteArray(deRef, '*');
- s << CPP_ARG0 << ");\n"
- << PYTHON_RETURN_VAR << " = ";
- if (!func->isVoid()) {
- writeToPythonConversion(s, func->type(), metaClass,
- CPP_RETURN_VAR);
- } else {
- s << "Py_None;\n" << "Py_INCREF(Py_None)";
- }
- s << ";\n";
- }
- }
- s << '}';
- }
+ const auto op = rfunc->comparisonOperatorType().value();
+ s << "case " << AbstractMetaFunction::pythonRichCompareOpCode(op)
+ << ":\n" << indent;
+
+ int alternativeNumericTypes = 0;
+ for (const auto &func : overloads) {
+ if (!func->isStatic() &&
+ ShibokenGenerator::isNumber(func->arguments().at(0).type().typeEntry()))
+ alternativeNumericTypes++;
+ }
- s << " else {\n";
- if (op == AbstractMetaFunction::OperatorEqual ||
- op == AbstractMetaFunction::OperatorNotEqual) {
- Indentation indent(s);
- s << PYTHON_RETURN_VAR << " = "
- << (op == AbstractMetaFunction::OperatorEqual ? "Py_False" : "Py_True") << ";\n"
- << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n";
+ bool first = true;
+ OverloadData overloadData(overloads, api());
+ const OverloadDataList &nextOverloads = overloadData.children();
+ for (const auto &od : nextOverloads) {
+ const auto func = od->referenceFunction();
+ if (func->isStatic())
+ continue;
+ auto argType = getArgumentType(func, 0);
+ if (!first) {
+ s << " else ";
} else {
- Indentation indent(s);
- s << "goto " << baseName << "_RichComparison_TypeError;\n";
+ first = false;
}
- s << "}\n\n";
-
- s << "break;\n";
- }
- s << "default:\n";
- {
- Indentation indent(s);
- s << richCompareComment
- << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n"
- << "goto " << baseName << "_RichComparison_TypeError;\n";
+ s << "if (";
+ writeTypeCheck(s, argType, PYTHON_ARG,
+ alternativeNumericTypes == 1 || isPyInt(argType));
+ s << ") {\n" << indent
+ << "// " << func->signature() << '\n';
+ writeArgumentConversion(s, argType, CPP_ARG0,
+ PYTHON_ARG, ErrorReturn::Default,
+ metaClass,
+ QString(), func->isUserAdded());
+ // If the function is user added, use the inject code
+ bool generateOperatorCode = true;
+ if (func->isUserAdded()) {
+ CodeSnipList snips = func->injectedCodeSnips();
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, func,
+ false /* uses PyArgs */, &func->arguments().constLast());
+ generateOperatorCode = false;
+ }
+ }
+ if (generateOperatorCode) {
+ if (!func->isVoid())
+ s << func->type().cppSignature() << " " << CPP_RETURN_VAR << " = ";
+ // expression
+ if (func->isPointerOperator())
+ s << '&';
+ s << CPP_SELF_VAR << ' '
+ << AbstractMetaFunction::cppComparisonOperator(op) << " (";
+ auto generatorArg = GeneratorArgument::fromMetaType(argType);
+ if (generatorArg.indirections != 0)
+ s << QByteArray(generatorArg.indirections, '*');
+ s << CPP_ARG0 << ");\n"
+ << PYTHON_RETURN_VAR << " = ";
+ if (!func->isVoid()) {
+ writeToPythonConversion(s, func->type(), metaClass,
+ CPP_RETURN_VAR);
+ } else {
+ s << "Py_None;\n" << "Py_INCREF(Py_None)";
+ }
+ s << ";\n";
+ }
+ s << outdent << '}';
}
- }
- s << "}\n\n";
-
- writeRichCompareFunctionFooter(s, baseName);
-}
-
-void CppGenerator::writeRichCompareFunctionFooter(TextStream &s,
- const QString &baseName)
-{
- s << "if (" << PYTHON_RETURN_VAR << " && !PyErr_Occurred())\n";
- {
- Indentation indent(s);
- s << "return " << PYTHON_RETURN_VAR << ";\n";
- }
- s << baseName << "_RichComparison_TypeError:\n"
- << "Shiboken::Errors::setOperatorNotImplemented();\n"
- << ErrorReturn::Default << '\n' << outdent << "}\n\n";
-}
-
-using ComparisonOperatorList = QList<AbstractMetaFunction::ComparisonOperatorType>;
-
-// Return the available comparison operators for smart pointers
-static ComparisonOperatorList smartPointeeComparisons(const GeneratorContext &context)
-{
- Q_ASSERT(context.forSmartPointer());
- auto *te = context.preciseType().instantiations().constFirst().typeEntry();
- if (te->isExtendedCppPrimitive()) { // Primitive pointee types have all
- return {AbstractMetaFunction::OperatorEqual,
- AbstractMetaFunction::OperatorNotEqual,
- AbstractMetaFunction::OperatorLess,
- AbstractMetaFunction::OperatorLessEqual,
- AbstractMetaFunction::OperatorGreater,
- AbstractMetaFunction::OperatorGreaterEqual};
- }
-
- auto *pointeeClass = context.pointeeClass();
- if (!pointeeClass)
- return {};
-
- ComparisonOperatorList result;
- const auto &comparisons =
- pointeeClass->operatorOverloads(OperatorQueryOption::SymmetricalComparisonOp);
- for (const auto &f : comparisons) {
- const auto ct = f->comparisonOperatorType().value();
- if (!result.contains(ct))
- result.append(ct);
- }
- return result;
-}
-
-void CppGenerator::writeSmartPointerRichCompareFunction(TextStream &s,
- const GeneratorContext &context) const
-{
- static const char selfPointeeVar[] = "cppSelfPointee";
- static const char cppArg0PointeeVar[] = "cppArg0Pointee";
- const AbstractMetaClass *metaClass = context.metaClass();
- QString baseName = cpythonBaseName(metaClass);
- writeRichCompareFunctionHeader(s, baseName, context);
-
- s << "if (";
- writeTypeCheck(s, context.preciseType(), PYTHON_ARG);
- s << ") {\n" << indent;
- writeArgumentConversion(s, context.preciseType(), CPP_ARG0,
- PYTHON_ARG, ErrorReturn::Default, metaClass);
-
- const auto *te = context.preciseType().typeEntry();
- Q_ASSERT(te->isSmartPointer());
- const auto *ste = static_cast<const SmartPointerTypeEntry *>(te);
-
- s << "const auto *" << selfPointeeVar << " = " << CPP_SELF_VAR
- << '.' << ste->getter() << "();\n";
- s << "const auto *" << cppArg0PointeeVar << " = " << CPP_ARG0
- << '.' << ste->getter() << "();\n";
-
- // If we have an object without any comparisons, only generate a simple
- // equality check by pointee address
- auto availableOps = smartPointeeComparisons(context);
- const bool comparePointeeAddressOnly = availableOps.isEmpty();
- if (comparePointeeAddressOnly) {
- availableOps << AbstractMetaFunction::OperatorEqual
- << AbstractMetaFunction::OperatorNotEqual;
- } else {
- // For value types with operators, we complain about nullptr
- s << "if (" << selfPointeeVar << " == nullptr || " << cppArg0PointeeVar
- << " == nullptr) {\n" << indent
- << "PyErr_SetString(PyExc_NotImplementedError, \"nullptr passed to comparison.\");\n"
- << ErrorReturn::Default << '\n' << outdent << "}\n";
- }
-
- s << "bool " << CPP_RETURN_VAR << "= false;\n"
- << "switch (op) {\n";
- for (auto op : availableOps) {
- s << "case " << AbstractMetaFunction::pythonRichCompareOpCode(op) << ":\n"
- << indent << CPP_RETURN_VAR << " = ";
- if (comparePointeeAddressOnly) {
- s << selfPointeeVar << ' ' << AbstractMetaFunction::cppComparisonOperator(op)
- << ' ' << cppArg0PointeeVar << ";\n";
+ s << " else {\n";
+ if (op == AbstractMetaFunction::OperatorEqual ||
+ op == AbstractMetaFunction::OperatorNotEqual) {
+ s << indent << PYTHON_RETURN_VAR << " = "
+ << (op == AbstractMetaFunction::OperatorEqual ? "Py_False" : "Py_True") << ";\n"
+ << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n" << outdent;
} else {
- // Shortcut for equality: Check pointee address
- if (op == AbstractMetaFunction::OperatorEqual
- || op == AbstractMetaFunction::OperatorLessEqual
- || op == AbstractMetaFunction::OperatorGreaterEqual) {
- s << selfPointeeVar << " == " << cppArg0PointeeVar << " || ";
- }
- // Generate object's comparison
- s << "*" << selfPointeeVar << ' '
- << AbstractMetaFunction::cppComparisonOperator(op) << " *"
- << cppArg0PointeeVar << ";\n";
+ s << indent << "return Shiboken::returnFromRichCompare("
+ << PYTHON_RETURN_VAR << ");\n" << outdent;
}
- s << "break;\n" << outdent;
+ s << "}\n\n";
+ s << "break;\n" << outdent;
}
- if (availableOps.size() < 6) {
- s << "default:\n" << indent
- << richCompareComment
- << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n" << outdent;
- }
- s << "}\n" << PYTHON_RETURN_VAR << " = " << CPP_RETURN_VAR
- << " ? Py_True : Py_False;\n"
- << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n";
-
- s << outdent << "} else {\n" << indent
- << "goto " << baseName << "_RichComparison_TypeError;\n"
- << outdent << "}\n";
-
- writeRichCompareFunctionFooter(s, baseName);
+ s << "default:\n" << indent
+ << richCompareComment
+ << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n"
+ << outdent << outdent << "}\n\n"
+ << "return Shiboken::returnFromRichCompare(" << PYTHON_RETURN_VAR << ");\n" << outdent
+ << "}\n\n";
}
// Return a flag combination for PyMethodDef
@@ -5334,9 +5078,9 @@ QByteArrayList CppGenerator::methodDefinitionParameters(const OverloadData &over
}
// METH_STATIC causes a crash when used for global functions (also from
// invisible namespaces).
- auto *ownerClass = overloadData.referenceFunction()->ownerClass();
+ const auto ownerClass = overloadData.referenceFunction()->ownerClass();
if (ownerClass
- && !invisibleTopNamespaces().contains(const_cast<AbstractMetaClass *>(ownerClass))) {
+ && !invisibleTopNamespaces().contains(std::const_pointer_cast<AbstractMetaClass>(ownerClass))) {
if (overloadData.hasStaticFunction())
result.append(QByteArrayLiteral("METH_STATIC"));
if (overloadData.hasClassMethod())
@@ -5356,7 +5100,7 @@ QList<PyMethodDefEntry>
QList<PyMethodDefEntry> result;
result.reserve(names.size());
for (const auto &name : names)
- result.append({name, funcName, parameters});
+ result.append({name, funcName, parameters, {}});
return result;
}
@@ -5378,10 +5122,15 @@ QString CppGenerator::signatureParameter(const AbstractMetaArgument &arg) const
const AbstractMetaFunctionCList conversions =
api().implicitConversions(metaType);
for (const auto &f : conversions) {
- if (f->isConstructor() && !f->arguments().isEmpty())
- signatures << f->arguments().constFirst().type().pythonSignature();
- else if (f->isConversionOperator())
+ if (f->isConstructor() && !f->arguments().isEmpty()) {
+ // PYSIDE-2712: modified types from converting constructors are not always correct
+ // candidates if they are modified by the type system reference
+ if (!f->arguments().constFirst().isTypeModified()) {
+ signatures << f->arguments().constFirst().type().pythonSignature();
+ }
+ } else if (f->isConversionOperator()) {
signatures << f->ownerClass()->fullName();
+ }
}
const qsizetype size = signatures.size();
@@ -5395,12 +5144,6 @@ QString CppGenerator::signatureParameter(const AbstractMetaArgument &arg) const
if (size > 1)
s << ']';
- if (!arg.defaultValueExpression().isEmpty()) {
- s << '=';
- QString e = arg.defaultValueExpression();
- e.replace(u"::"_s, u"."_s);
- s << e;
- }
return result;
}
@@ -5417,71 +5160,80 @@ void CppGenerator::writeSignatureInfo(TextStream &s, const OverloadData &overloa
// PYSIDE-1328: `self`-ness cannot be computed in Python because there are mixed cases.
// Toplevel functions like `PySide6.QtCore.QEnum` are always self-less.
if (!(f->isStatic()) && f->ownerClass())
- args << u"self"_s;
+ args << PYTHON_SELF_VAR;
const auto &arguments = f->arguments();
for (qsizetype i = 0, size = arguments.size(); i < size; ++i) {
- QString t = f->pyiTypeReplaced(i + 1);
- if (t.isEmpty()) {
- t = signatureParameter(arguments.at(i));
- } else {
- t.prepend(u':');
- t.prepend(arguments.at(i).name());
+ const auto n = i + 1;
+ const auto &arg = arguments.at(i);
+ if (!f->argumentRemoved(n)) {
+ QString t = f->pyiTypeReplaced(n);
+ if (t.isEmpty()) {
+ t = signatureParameter(arg);
+ } else {
+ t.prepend(u':');
+ t.prepend(arg.name());
+ }
+ QString defaultValue = arg.defaultValueExpression();
+ if (!defaultValue.isEmpty())
+ t += u'=' + defaultValue.replace(u"::"_s, u"."_s);
+ args.append(t);
}
- args.append(t);
}
// mark the multiple signatures as such, to make it easier to generate different code
if (multiple)
s << idx-- << ':';
s << funcName << '(' << args.join(u',') << ')';
- if (!f->isVoid()) {
- QString t = f->pyiTypeReplaced(0);
- if (t.isEmpty())
- t = f->type().pythonSignature();
- s << "->" << t;
- }
+
+ QString returnType = f->pyiTypeReplaced(0); // pyi or modified type
+ if (returnType.isEmpty() && !f->isVoid())
+ returnType = f->type().pythonSignature();
+ if (!returnType.isEmpty())
+ s << "->" << returnType;
+
s << '\n';
}
}
-void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums,
- ErrorReturn errorReturn) const
+void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums)
{
if (enums.isEmpty())
return;
- bool preambleWrittenE = false;
- bool preambleWrittenF = false;
- for (const AbstractMetaEnum &cppEnum : qAsConst(enums)) {
+ bool preambleWritten = false;
+ bool etypeUsed = false;
+
+ for (const AbstractMetaEnum &cppEnum : std::as_const(enums)) {
if (cppEnum.isPrivate())
continue;
- if (!preambleWrittenE) {
+ if (!preambleWritten) {
s << "// Initialization of enums.\n"
+ << "Shiboken::AutoDecRef tpDict{};\n"
<< "PyTypeObject *EType{};\n\n";
- preambleWrittenE = true;
- }
- if (!preambleWrittenF && cppEnum.typeEntry()->flags()) {
- s << "// Initialization of enums, flags part.\n"
- << "PyTypeObject *FType{};\n\n";
- preambleWrittenF = true;
+ preambleWritten = true;
}
- writeEnumInitialization(s, cppEnum, errorReturn);
+ ConfigurableScope configScope(s, cppEnum.typeEntry());
+ etypeUsed |= writeEnumInitialization(s, cppEnum);
}
+ if (preambleWritten && !etypeUsed)
+ s << sbkUnusedVariableCast("EType");
}
-static QString mangleName(QString name)
+static qsizetype maxLineLength(const QStringList &list)
{
- if (name == u"None" || name == u"False" || name == u"True")
- name += u'_';
- return name;
+ qsizetype result = 0;
+ for (const auto &s : list) {
+ if (auto len = s.size(); len > result)
+ result = len;
+ }
+ return result;
}
-void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum &cppEnum,
- ErrorReturn errorReturn) const
+bool CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum &cppEnum)
{
- const AbstractMetaClass *enclosingClass = cppEnum.targetLangEnclosingClass();
- bool hasUpperEnclosingClass = enclosingClass
- && enclosingClass->targetLangEnclosingClass() != nullptr;
- const EnumTypeEntry *enumTypeEntry = cppEnum.typeEntry();
+ const auto enclosingClass = cppEnum.targetLangEnclosingClass();
+ const bool hasUpperEnclosingClass = enclosingClass
+ && enclosingClass->targetLangEnclosingClass();
+ EnumTypeEntryCPtr enumTypeEntry = cppEnum.typeEntry();
QString enclosingObjectVariable;
if (enclosingClass)
enclosingObjectVariable = cpythonTypeName(enclosingClass);
@@ -5494,102 +5246,115 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
s << (cppEnum.isAnonymous() ? "anonymous enum identified by enum value" : "enum");
s << " '" << cppEnum.name() << "'.\n";
- QString enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
- if (!cppEnum.isAnonymous()) {
- int packageLevel = packageName().count(u'.') + 1;
- FlagsTypeEntry *flags = enumTypeEntry->flags();
- if (flags) {
- // The following could probably be made nicer:
- // We need 'flags->flagsName()' with the full module/class path.
- QString fullPath = getClassTargetFullName(cppEnum);
- fullPath.truncate(fullPath.lastIndexOf(u'.') + 1);
- s << "FType = PySide::QFlags::create(\""
- << packageLevel << ':' << fullPath << flags->flagsName() << "\", \n" << indent
- << cpythonEnumName(cppEnum) << "_number_slots);\n" << outdent
- << cpythonTypeNameExt(flags) << " = FType;\n";
- }
+ const QString userType = cppEnum.typeEntry()->cppType();
+ const bool isSigned = cppEnum.isSigned() && !userType.contains(u"unsigned"_s);
+ const bool isAccessible = !avoidProtectedHack() || !cppEnum.isProtected();
+ const auto enumValues = cppEnum.nonRejectedValues();
- s << "EType = Shiboken::Enum::"
- << ((enclosingClass
- || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum")
- << '(' << enclosingObjectVariable << ',' << '\n';
- {
- Indentation indent(s);
- s << '"' << cppEnum.name() << "\",\n"
- << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n"
- << '"' << cppEnum.qualifiedCppName() << '"';
- if (flags)
- s << ",\nFType";
- s << ");\n";
+ const QString prefix = cppEnum.name();
+
+ const QString intType = userType.isEmpty() ? cppEnum.underlyingType() : userType;
+
+ // Create a list of values
+ const QString initializerValues = prefix + u"_InitializerValues"_s;
+ const QString initializerName = prefix + u"_Initializer"_s;
+
+ // Build maybe array of enum names.
+ if (cppEnum.enumKind() != AnonymousEnum) {
+ s << "const char *" << initializerName << "[] = {\n" << indent;
+ for (const auto &enumValue : enumValues) {
+ QString name = mangleName(enumValue.name());
+ s << '\"' << name << "\",\n";
}
- s << "if (!EType)\n"
- << indent << errorReturn << outdent << '\n';
+ s << "nullptr};\n" << outdent;
}
- for (const AbstractMetaEnumValue &enumValue : cppEnum.values()) {
- if (enumTypeEntry->isEnumValueRejected(enumValue.name()))
- continue;
+ int targetHexLen = 0;
+ QString usedIntType = userType;
+ if (usedIntType.isEmpty()) {
+ const int usedBits = cppEnum.usedBits();
+ targetHexLen = usedBits / 4;
+ usedIntType = AbstractMetaEnum::intTypeForSize(usedBits, cppEnum.isSigned());
+ }
- QString enumValueText;
- if (!avoidProtectedHack() || !cppEnum.isProtected()) {
- enumValueText = u"(long) "_s;
- if (cppEnum.enclosingClass())
- enumValueText += cppEnum.enclosingClass()->qualifiedCppName() + u"::"_s;
- // Fully qualify the value which is required for C++ 11 enum classes.
- if (!cppEnum.isAnonymous())
- enumValueText += cppEnum.name() + u"::"_s;
- enumValueText += enumValue.name();
- } else {
- enumValueText += enumValue.value().toString();
- }
+ if (usedIntType != intType)
+ s << "// \"" << usedIntType << "\" used instead of \"" << intType << "\"\n";
+
+ // Calculating formatting columns
+ QString enumValuePrefix;
+ if (isAccessible) {
+ if (cppEnum.enclosingClass())
+ enumValuePrefix += cppEnum.enclosingClass()->qualifiedCppName() + u"::"_s;
+ if (!cppEnum.isAnonymous())
+ enumValuePrefix += cppEnum.name() + u"::"_s;
+ }
- const QString mangledName = mangleName(enumValue.name());
- switch (cppEnum.enumKind()) {
- case AnonymousEnum:
+ // Build array of enum values
+ if (enumValues.isEmpty()) {
+ s << "const " << usedIntType << " *" << initializerValues << "{};\n";
+ } else {
+ QStringList values;
+ values.reserve(enumValues.size());
+ s << "constexpr " << usedIntType << ' ' << initializerValues << "[] = {\n" << indent;
+ for (qsizetype idx = 0, last = enumValues.size() - 1; idx <= last; ++idx) {
+ const auto &enumValue = enumValues.at(idx);
+ QString line = usedIntType + u'(' + (isAccessible
+ ? enumValuePrefix + enumValue.name()
+ : enumValue.value().toString()) + u')';
+ if (idx != last)
+ line += u',';
+ values.append(line);
+ }
+
+ const auto len = maxLineLength(values) + 1;
+ for (qsizetype idx = 0, size = enumValues.size(); idx < size; ++idx) {
+ const auto &enumValue = enumValues.at(idx).value();
+ const char *numberSpace = enumValue.isNegative() ? " " : " ";
+ s << values.at(idx) << Pad(' ', len - values.at(idx).size())
+ << "//" << numberSpace << enumValue.toHex(targetHexLen)
+ << numberSpace << enumValue.toString() << '\n';
+ }
+ s << "};\n" << outdent;
+ }
+
+ // Build initialization of anonymous enums
+ if (cppEnum.enumKind() == AnonymousEnum) {
+ int idx = 0;
+ for (const auto &enumValue : enumValues) {
+ const QString mangledName = mangleName(enumValue.name());
+ const QString pyValue = initializerValues + u'[' + QString::number(idx++) + u']';
if (enclosingClass || hasUpperEnclosingClass) {
- s << "{\n";
- {
- Indentation indentation(s);
- s << "PyObject *anonEnumItem = PyLong_FromLong(" << enumValueText << ");\n"
- << "if (PyDict_SetItemString(reinterpret_cast<PyTypeObject *>("
- << enclosingObjectVariable
- << ")->tp_dict, \"" << mangledName << "\", anonEnumItem) < 0)\n"
- << indent << errorReturn << outdent
- << "Py_DECREF(anonEnumItem);\n";
- }
- s << "}\n";
+ s << "tpDict.reset(PepType_GetDict(reinterpret_cast<PyTypeObject *>("
+ << enclosingObjectVariable << ")));\n"
+ << "PyDict_SetItemString(tpDict.object(), \"" << mangledName << "\",\n"
+ << indent << (isSigned ? "PyLong_FromLongLong" : "PyLong_FromUnsignedLongLong")
+ << "(" << pyValue << "));\n" << outdent;
} else {
- s << "if (PyModule_AddIntConstant(module, \"" << mangledName << "\", ";
- s << enumValueText << ") < 0)\n" << indent << errorReturn << outdent;
+ s << "PyModule_AddObject(module, \"" << mangledName << "\",\n" << indent
+ << (isSigned ? "PyLong_FromLongLong" : "PyLong_FromUnsignedLongLong") << "("
+ << pyValue << "));\n" << outdent;
}
- break;
- case CEnum: {
- s << "if (!Shiboken::Enum::";
- s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem"
- : "createGlobalEnumItem");
- s << '(' << "EType" << ',' << '\n';
- Indentation indent(s);
- s << enclosingObjectVariable << ", \"" << mangledName << "\", "
- << enumValueText << "))\n" << errorReturn;
- }
- break;
- case EnumClass: {
- s << "if (!Shiboken::Enum::createScopedEnumItem("
- << "EType" << ",\n";
- Indentation indentation(s);
- s << "EType" << ", \"" << mangledName << "\", "
- << enumValueText << "))\n" << errorReturn;
- }
- break;
}
}
- s << "// PYSIDE-1735: Resolving the whole enum class at the end for API compatibility.\n"
- << "EType = morphLastEnumToPython();\n"
- << enumVarTypeObj << " = EType;\n";
+
+ bool etypeUsed = false;
+
+ QString enumVarTypeObj = cpythonTypeNameExtSet(enumTypeEntry);
+ if (!cppEnum.isAnonymous()) {
+ int packageLevel = packageName().count(u'.') + 1;
+ s << "EType = Shiboken::Enum::"
+ << "createPythonEnum"
+ << '(' << enclosingObjectVariable << ",\n" << indent
+ << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n"
+ << initializerName << ", " << initializerValues << ");\n" << outdent
+ << enumVarTypeObj << " = EType;\n";
+ etypeUsed = true;
+ }
+
if (cppEnum.typeEntry()->flags()) {
s << "// PYSIDE-1735: Mapping the flags class to the same enum class.\n"
- << cpythonTypeNameExt(cppEnum.typeEntry()->flags()) << " =\n"
- << indent << "mapFlagsToSameEnum(FType, EType);\n" << outdent;
+ << cpythonTypeNameExtSet(cppEnum.typeEntry()->flags()) << " =\n"
+ << indent << "EType;\n" << outdent;
}
writeEnumConverterInitialization(s, cppEnum);
@@ -5597,9 +5362,11 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
if (cppEnum.typeEntry()->flags())
s << "/flags";
s << ".\n\n";
+
+ return etypeUsed;
}
-void CppGenerator::writeSignalInitialization(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeSignalInitialization(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
// Try to check something and print some warnings
const auto &signalFuncs = metaClass->cppSignalFunctions();
@@ -5621,134 +5388,11 @@ void CppGenerator::writeSignalInitialization(TextStream &s, const AbstractMetaCl
}
}
- s << "PySide::Signal::registerSignals(pyType, &::"
+ s << "PySide::Signal::registerSignals(pyType, &" << m_gsp
<< metaClass->qualifiedCppName() << "::staticMetaObject);\n";
}
-void CppGenerator::writeFlagsToLong(TextStream &s, const AbstractMetaEnum &cppEnum)
-{
- FlagsTypeEntry *flagsEntry = cppEnum.typeEntry()->flags();
- if (!flagsEntry)
- return;
- s << "static PyObject *" << cpythonEnumName(cppEnum) << "_long(PyObject *self)\n"
- << "{\n" << indent
- << "int val;\n";
- AbstractMetaType flagsType = AbstractMetaType::fromTypeEntry(flagsEntry);
- s << cpythonToCppConversionFunction(flagsType) << "self, &val);\n"
- << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<int>(), &val);\n"
- << outdent << "}\n";
-}
-
-void CppGenerator::writeFlagsNonZero(TextStream &s, const AbstractMetaEnum &cppEnum)
-{
- FlagsTypeEntry *flagsEntry = cppEnum.typeEntry()->flags();
- if (!flagsEntry)
- return;
- s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject *self)\n";
- s << "{\n" << indent << "int val;\n";
- AbstractMetaType flagsType = AbstractMetaType::fromTypeEntry(flagsEntry);
- s << cpythonToCppConversionFunction(flagsType) << "self, &val);\n"
- << "return val != 0;\n"
- << outdent << "}\n";
-}
-
-void CppGenerator::writeFlagsMethods(TextStream &s, const AbstractMetaEnum &cppEnum)
-{
- writeFlagsBinaryOperator(s, cppEnum, u"and"_s, u"&"_s);
- writeFlagsBinaryOperator(s, cppEnum, u"or"_s, u"|"_s);
- writeFlagsBinaryOperator(s, cppEnum, u"xor"_s, u"^"_s);
-
- writeFlagsUnaryOperator(s, cppEnum, u"invert"_s, u"~"_s);
- writeFlagsToLong(s, cppEnum);
- writeFlagsNonZero(s, cppEnum);
-
- s << '\n';
-}
-
-void CppGenerator::writeFlagsNumberMethodsDefinition(TextStream &s, const AbstractMetaEnum &cppEnum)
-{
- QString cpythonName = cpythonEnumName(cppEnum);
-
- s << "static PyType_Slot " << cpythonName << "_number_slots[] = {\n" << indent
- << "{Py_nb_bool, reinterpret_cast<void *>(" << cpythonName << "__nonzero)},\n"
- << "{Py_nb_invert, reinterpret_cast<void *>(" << cpythonName << "___invert__)},\n"
- << "{Py_nb_and, reinterpret_cast<void *>(" << cpythonName << "___and__)},\n"
- << "{Py_nb_xor, reinterpret_cast<void *>(" << cpythonName << "___xor__)},\n"
- << "{Py_nb_or, reinterpret_cast<void *>(" << cpythonName << "___or__)},\n"
- << "{Py_nb_int, reinterpret_cast<void *>(" << cpythonName << "_long)},\n"
- << "{Py_nb_index, reinterpret_cast<void *>(" << cpythonName << "_long)},\n"
- << "{0, " << NULL_PTR << "} // sentinel\n" << outdent
- << "};\n\n";
-}
-
-void CppGenerator::writeFlagsNumberMethodsDefinitions(TextStream &s,
- const AbstractMetaEnumList &enums)
-{
- for (const AbstractMetaEnum &e : enums) {
- if (!e.isAnonymous() && !e.isPrivate() && e.typeEntry()->flags()) {
- writeFlagsMethods(s, e);
- writeFlagsNumberMethodsDefinition(s, e);
- s << '\n';
- }
- }
-}
-
-void CppGenerator::writeFlagsBinaryOperator(TextStream &s, const AbstractMetaEnum &cppEnum,
- const QString &pyOpName, const QString &cppOpName)
-{
- FlagsTypeEntry *flagsEntry = cppEnum.typeEntry()->flags();
- Q_ASSERT(flagsEntry);
-
- s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName
- << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")\n{\n" << indent;
-
- AbstractMetaType flagsType = AbstractMetaType::fromTypeEntry(flagsEntry);
- s << "::" << flagsEntry->originalName() << " cppResult, " << CPP_SELF_VAR
- << ", cppArg;\n"
- << CPP_SELF_VAR << " = static_cast<::" << flagsEntry->originalName()
- << ">(int(PyLong_AsLong(self)));\n"
- // PYSIDE-1436: Need to error check self as well because operators are used
- // sometimes with swapped args.
- << "if (PyErr_Occurred())\n" << indent
- << "return nullptr;\n" << outdent
- << "cppArg = static_cast<" << flagsEntry->originalName()
- << ">(int(PyLong_AsLong(" << PYTHON_ARG << ")));\n"
- << "if (PyErr_Occurred())\n" << indent
- << "return nullptr;\n" << outdent
- << "cppResult = " << CPP_SELF_VAR << " " << cppOpName << " cppArg;\n"
- << "return ";
- writeToPythonConversion(s, flagsType, nullptr, u"cppResult"_s);
- s << ";\n" << outdent << "}\n\n";
-}
-
-void CppGenerator::writeFlagsUnaryOperator(TextStream &s, const AbstractMetaEnum &cppEnum,
- const QString &pyOpName,
- const QString &cppOpName, bool boolResult)
-{
- FlagsTypeEntry *flagsEntry = cppEnum.typeEntry()->flags();
- Q_ASSERT(flagsEntry);
-
- s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName
- << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")\n{\n" << indent;
-
- AbstractMetaType flagsType = AbstractMetaType::fromTypeEntry(flagsEntry);
- s << "::" << flagsEntry->originalName() << " " << CPP_SELF_VAR << ";\n"
- << cpythonToCppConversionFunction(flagsType) << "self, &" << CPP_SELF_VAR
- << ");\n";
- if (boolResult)
- s << "bool";
- else
- s << "::" << flagsEntry->originalName();
- s << " cppResult = " << cppOpName << CPP_SELF_VAR << ";\n"
- << "return ";
- if (boolResult)
- s << "PyBool_FromLong(cppResult)";
- else
- writeToPythonConversion(s, flagsType, nullptr, u"cppResult"_s);
- s << ";\n" << outdent << "}\n\n";
-}
-
-QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass)
+QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClassCPtr &metaClass)
{
QString initFunctionName;
// Disambiguate namespaces per module to allow for extending them.
@@ -5759,7 +5403,8 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me
return initFunctionName;
}
-QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass)
+QString
+ CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClassCPtr &metaClass)
{
return u"init_"_s + getSimpleClassInitFunctionName(metaClass)
+ u"StaticFields"_s;
@@ -5790,8 +5435,8 @@ void CppGenerator::writeSignatureStrings(TextStream &s,
}
// Return the class name for which to invoke the destructor
-QString CppGenerator::destructorClassName(const AbstractMetaClass *metaClass,
- const GeneratorContext &classContext) const
+QString CppGenerator::destructorClassName(const AbstractMetaClassCPtr &metaClass,
+ const GeneratorContext &classContext)
{
if (metaClass->isNamespace() || metaClass->hasPrivateDestructor())
return {};
@@ -5808,14 +5453,69 @@ QString CppGenerator::destructorClassName(const AbstractMetaClass *metaClass,
return metaClass->qualifiedCppName();
}
+// Return the base type entries for introduceWrapperType()
+static ComplexTypeEntryCList pyBaseTypeEntries(const AbstractMetaClassCPtr &metaClass)
+{
+ ComplexTypeEntryCList result;
+ if (metaClass->isNamespace()) {
+ if (auto extended = metaClass->extendedNamespace())
+ result.append(extended->typeEntry());
+ return result;
+ }
+
+ const auto &baseClasses = metaClass->typeSystemBaseClasses();
+ for (auto base : baseClasses) {
+ for (; base != nullptr; base = base->baseClass()) { // Find a type that is not disabled.
+ const auto ct = base->typeEntry()->codeGeneration();
+ if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass)
+ break;
+ }
+ result.append(base->typeEntry());
+ }
+ return result;
+}
+
+// Return the base type strings for introduceWrapperType()
+QStringList CppGenerator::pyBaseTypes(const AbstractMetaClassCPtr &metaClass)
+{
+ const auto &baseEntries = pyBaseTypeEntries(metaClass);
+ QStringList result;
+ for (const auto &baseEntry : baseEntries)
+ result.append("reinterpret_cast<PyObject *>("_L1 + cpythonTypeNameExt(baseEntry) + u')');
+ if (result.isEmpty()) // no base classes -> SbkObjectType.
+ result.append(sbkObjectTypeF);
+ return result;
+}
+
+void CppGenerator::writeInitInheritance(TextStream &s) const
+{
+ s << "static void " << initInheritanceFunction << "()\n{\n" << indent
+ << "auto &bm = Shiboken::BindingManager::instance();\n"
+ << sbkUnusedVariableCast("bm");
+ for (const auto &cls : api().classes()){
+ auto te = cls->typeEntry();
+ if (shouldGenerate(te)) {
+ const auto &baseEntries = pyBaseTypeEntries(cls);
+ if (!baseEntries.isEmpty()) {
+ const QString childTypeInitStruct = typeInitStruct(cls->typeEntry());
+ for (const auto &baseEntry : baseEntries) {
+ s << "bm.addClassInheritance(&" << typeInitStruct(baseEntry) << ",\n"
+ << Pad(' ', 23) << '&' << childTypeInitStruct << ");\n";
+ }
+ }
+ }
+ }
+ s << outdent << "}\n\n";
+}
+
void CppGenerator::writeClassRegister(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext,
const QString &signatures) const
{
- const ComplexTypeEntry *classTypeEntry = metaClass->typeEntry();
+ ComplexTypeEntryCPtr classTypeEntry = metaClass->typeEntry();
- const AbstractMetaClass *enc = metaClass->targetLangEnclosingClass();
+ AbstractMetaClassCPtr enc = metaClass->targetLangEnclosingClass();
QString enclosingObjectVariable = enc ? u"enclosingClass"_s : u"module"_s;
QString pyTypeName = cpythonTypeName(metaClass);
@@ -5823,103 +5523,84 @@ void CppGenerator::writeClassRegister(TextStream &s,
// PYSIDE-510: Create a signatures string for the introspection feature.
writeSignatureStrings(s, signatures, initFunctionName, "functions");
- s << "void init_" << initFunctionName;
- s << "(PyObject *" << enclosingObjectVariable << ")\n{\n" << indent;
+ s << "PyTypeObject *init_" << initFunctionName
+ << "(PyObject *" << enclosingObjectVariable << ")\n{\n" << indent;
+
+ const QString globalTypeVarExpr = !classContext.forSmartPointer()
+ ? cpythonTypeNameExtSet(classTypeEntry)
+ : cpythonTypeNameExtSet(classContext.preciseType());
+ s << "if (" << globalTypeVarExpr << " != nullptr)\n" << indent
+ << "return " << globalTypeVarExpr << ";\n\n" << outdent;
// Multiple inheritance
QString pyTypeBasesVariable = chopType(pyTypeName) + u"_Type_bases"_s;
- const auto &baseClasses = metaClass->typeSystemBaseClasses();
- if (metaClass->baseClassNames().size() > 1) {
- s << "PyObject *" << pyTypeBasesVariable
- << " = PyTuple_Pack(" << baseClasses.size() << ',' << '\n';
- Indentation indent(s);
- for (int i = 0, size = baseClasses.size(); i < size; ++i) {
- if (i)
- s << ",\n";
- s << "reinterpret_cast<PyObject *>("
- << cpythonTypeNameExt(baseClasses.at(i)->typeEntry()) << ')';
- }
- s << ");\n\n";
+ const QStringList pyBases = pyBaseTypes(metaClass);
+ s << "Shiboken::AutoDecRef " << pyTypeBasesVariable << "(PyTuple_Pack("
+ << pyBases.size() << ",\n" << indent;
+ for (qsizetype i = 0, size = pyBases.size(); i < size; ++i) {
+ if (i)
+ s << ",\n";
+ s << pyBases.at(i);
}
+ s << "));\n\n" << outdent;
// Create type and insert it in the module or enclosing class.
const QString typePtr = u"_"_s + chopType(pyTypeName)
+ u"_Type"_s;
- s << typePtr << " = Shiboken::ObjectType::introduceWrapperType(\n";
- {
- Indentation indent(s);
- // 1:enclosingObject
- s << enclosingObjectVariable << ",\n";
-
- // 2:typeName
- s << "\"" << metaClass->name() << "\",\n";
-
- // 3:originalName
- s << "\"";
- if (!classContext.forSmartPointer()) {
- s << metaClass->qualifiedCppName();
- if (classTypeEntry->isObject())
- s << '*';
- } else {
- s << classContext.preciseType().cppSignature();
- }
+ s << typePtr << " = Shiboken::ObjectType::introduceWrapperType(\n" << indent;
+ // 1:enclosingObject
+ s << enclosingObjectVariable << ",\n";
- s << "\",\n";
- // 4:typeSpec
- s << '&' << chopType(pyTypeName) << "_spec,\n";
+ // 2:typeName
+ s << "\"" << metaClass->name() << "\",\n";
- // 5:cppObjDtor
- QString dtorClassName = destructorClassName(metaClass, classContext);
- if (dtorClassName.isEmpty())
- s << "nullptr,\n";
- else
- s << "&Shiboken::callCppDestructor< ::" << dtorClassName << " >,\n";
-
- // 6:baseType: Find a type that is not disabled.
- auto base = metaClass->isNamespace()
- ? metaClass->extendedNamespace() : metaClass->baseClass();
- if (!metaClass->isNamespace()) {
- for (; base != nullptr; base = base->baseClass()) {
- const auto ct = base->typeEntry()->codeGeneration();
- if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass)
- break;
- }
- }
- if (base) {
- s << cpythonTypeNameExt(base->typeEntry()) << ",\n";
- } else {
- s << "0,\n";
- }
-
- // 7:baseTypes
- if (metaClass->baseClassNames().size() > 1)
- s << pyTypeBasesVariable << ',' << '\n';
- else
- s << "0,\n";
-
- // 8:wrapperflags
- QByteArrayList wrapperFlags;
- if (enc)
- wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass"));
- if (metaClass->deleteInMainThread())
- wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread"));
- if (wrapperFlags.isEmpty())
- s << '0';
- else
- s << wrapperFlags.join(" | ");
+ // 3:originalName
+ s << "\"";
+ if (!classContext.forSmartPointer()) {
+ s << metaClass->qualifiedCppName();
+ if (classTypeEntry->isObject())
+ s << '*';
+ } else {
+ s << classContext.preciseType().cppSignature();
}
- s << ");\nauto *pyType = " << pyTypeName << "; // references " << typePtr << "\n"
+
+ s << "\",\n";
+ // 4:typeSpec
+ s << '&' << chopType(pyTypeName) << "_spec,\n";
+
+ // 5:cppObjDtor
+ QString dtorClassName = destructorClassName(metaClass, classContext);
+ if (dtorClassName.isEmpty())
+ s << "nullptr,\n";
+ else
+ s << "&Shiboken::callCppDestructor< " << globalScopePrefix(classContext)
+ << dtorClassName << " >,\n";
+
+ // 7:baseTypes
+ s << pyTypeBasesVariable << ".object()," << '\n';
+
+ // 8:wrapperflags
+ QByteArrayList wrapperFlags;
+ if (enc)
+ wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass"));
+ if (metaClass->deleteInMainThread())
+ wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread"));
+ if (classTypeEntry->isValue())
+ wrapperFlags.append("Shiboken::ObjectType::WrapperFlags::Value"_ba);
+ if (wrapperFlags.isEmpty())
+ s << '0';
+ else
+ s << wrapperFlags.join(" | ");
+
+ s << outdent << ");\nauto *pyType = " << pyTypeName << "; // references "
+ << typePtr << "\n"
<< "InitSignatureStrings(pyType, " << initFunctionName << "_SignatureStrings);\n";
if (usePySideExtensions() && !classContext.forSmartPointer())
s << "SbkObjectType_SetPropertyStrings(pyType, "
<< chopType(pyTypeName) << "_PropertyStrings);\n";
-
- if (!classContext.forSmartPointer())
- s << cpythonTypeNameExt(classTypeEntry) << " = pyType;\n\n";
- else
- s << cpythonTypeNameExt(classContext.preciseType()) << " = pyType;\n\n";
+ s << globalTypeVarExpr << " = pyType;\n\n";
// Register conversions for the type.
writeConverterRegister(s, metaClass, classContext);
@@ -5934,7 +5615,7 @@ void CppGenerator::writeClassRegister(TextStream &s,
}
// Fill multiple inheritance data, if needed.
- const AbstractMetaClass *miClass = getMultipleInheritingClass(metaClass);
+ const auto miClass = getMultipleInheritingClass(metaClass);
if (miClass) {
s << "MultipleInheritanceInitFunction func = ";
if (miClass == metaClass) {
@@ -5951,14 +5632,19 @@ void CppGenerator::writeClassRegister(TextStream &s,
// Set typediscovery struct or fill the struct of another one
if (needsTypeDiscoveryFunction(metaClass)) {
- s << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(" << cpythonTypeName(metaClass)
- << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);\n\n";
+ s << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(\n" << indent
+ << cpythonTypeName(metaClass)
+ << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << outdent << "\n\n";
}
AbstractMetaEnumList classEnums = metaClass->enums();
metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
- writeEnumsInitialization(s, classEnums, ErrorReturn::Void);
+ if (!classContext.forSmartPointer() && !classEnums.isEmpty())
+ s << "// Pass the ..._EnumFlagInfo to the class.\n"
+ << "SbkObjectType_SetEnumFlagInfo(pyType, " << chopType(pyTypeName)
+ << "_EnumFlagInfo);\n\n";
+ writeEnumsInitialization(s, classEnums);
if (metaClass->hasSignals())
writeSignalInitialization(s, metaClass);
@@ -5978,25 +5664,40 @@ void CppGenerator::writeClassRegister(TextStream &s,
writeInitQtMetaTypeFunctionBody(s, classContext);
}
- if (usePySideExtensions() && metaClass->isQObject()) {
+ if (usePySideExtensions() && isQObject(metaClass)) {
s << "Shiboken::ObjectType::setSubTypeInitHook(pyType, &PySide::initQObjectSubType);\n"
- << "PySide::initDynamicMetaObject(pyType, &::"
- << metaClass->qualifiedCppName() << "::staticMetaObject, sizeof(";
- if (shouldGenerateCppWrapper(metaClass))
- s << wrapperName(metaClass);
- else
- s << "::" << metaClass->qualifiedCppName();
- s << "));\n";
+ << "PySide::initDynamicMetaObject(pyType, &" << m_gsp
+ << metaClass->qualifiedCppName() << "::staticMetaObject, sizeof("
+ << (shouldGenerateCppWrapper(metaClass)
+ ? wrapperName(metaClass) : getFullTypeName(metaClass))
+ << "));\n";
}
- s << outdent << "}\n";
+ s << "\nreturn pyType;\n" << outdent << "}\n";
}
-void CppGenerator::writeStaticFieldInitialization(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeStaticFieldInitialization(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass)
{
- s << "\nvoid " << getSimpleClassStaticFieldsInitFunctionName(metaClass)
- << "()\n{\n" << indent << "auto dict = reinterpret_cast<PyTypeObject *>("
- << cpythonTypeName(metaClass) << ")->tp_dict;\n";
+ // cpythonTypeName == "Sbk_QRhiShaderResourceBinding_Data_TypeF"
+ QString name = cpythonTypeName(metaClass);
+ const auto parts = QStringView{name}.split(u'_', Qt::SkipEmptyParts);
+ if (parts.size() < 4) {
+ s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
+ << "(PyObject *module)\n{\n" << indent
+ << "auto *obType = PyObject_GetAttrString(module, \"" << metaClass->name() << "\");\n"
+ << "auto *type = reinterpret_cast<PyTypeObject *>(obType);\n"
+ << "Shiboken::AutoDecRef dict(PepType_GetDict(type));\n";
+ } else {
+ s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
+ << "(PyObject *module)\n{\n" << indent
+ << "auto *obContainerType = PyObject_GetAttrString(module, \""
+ << parts.at(1) << "\");\n"
+ << "auto *obType = PyObject_GetAttrString(obContainerType, \""
+ << parts.at(2) << "\");\n"
+ << "auto *type = reinterpret_cast<PyTypeObject *>(obType);\n"
+ << "Shiboken::AutoDecRef dict(PepType_GetDict(type));\n";
+ }
for (const AbstractMetaField &field : metaClass->fields()) {
if (field.isStatic()) {
s << "PyDict_SetItemString(dict, \"" << field.name()
@@ -6005,7 +5706,7 @@ void CppGenerator::writeStaticFieldInitialization(TextStream &s, const AbstractM
s << ");\n";
}
}
- s << '\n' << outdent << "}\n";
+ s << "return type;\n" << outdent << "}\n";
}
enum class QtRegisterMetaType
@@ -6013,7 +5714,7 @@ enum class QtRegisterMetaType
None, Pointer, Value
};
-static bool hasQtMetaTypeRegistrationSpec(const AbstractMetaClass *c)
+static bool hasQtMetaTypeRegistrationSpec(const AbstractMetaClassCPtr &c)
{
return c->typeEntry()->qtMetaTypeRegistration() !=
TypeSystem::QtMetaTypeRegistration::Unspecified;
@@ -6022,7 +5723,7 @@ static bool hasQtMetaTypeRegistrationSpec(const AbstractMetaClass *c)
// Returns if and how to register the Qt meta type. By default, "pointer" for
// non-QObject object types and "value" for non-abstract, default-constructible
// value types.
-QtRegisterMetaType qtMetaTypeRegistration(const AbstractMetaClass *c)
+QtRegisterMetaType qtMetaTypeRegistration(const AbstractMetaClassCPtr &c)
{
if (c->isNamespace())
return QtRegisterMetaType::None;
@@ -6041,7 +5742,7 @@ QtRegisterMetaType qtMetaTypeRegistration(const AbstractMetaClass *c)
// Is there a "base" specification in some base class, meaning only the
// base class is to be registered?
- if (auto *base = recurseClassHierarchy(c, hasQtMetaTypeRegistrationSpec)) {
+ if (auto base = recurseClassHierarchy(c, hasQtMetaTypeRegistrationSpec)) {
const auto baseSpec = base->typeEntry()->qtMetaTypeRegistration();
if (baseSpec == TypeSystem::QtMetaTypeRegistration::BaseEnabled)
return QtRegisterMetaType::None;
@@ -6049,7 +5750,7 @@ QtRegisterMetaType qtMetaTypeRegistration(const AbstractMetaClass *c)
// Default.
if (isObject)
- return c->isQObject() ? QtRegisterMetaType::None : QtRegisterMetaType::Pointer;
+ return isQObject(c) ? QtRegisterMetaType::None : QtRegisterMetaType::Pointer;
return !c->isAbstract() && c->isDefaultConstructible()
? QtRegisterMetaType::Value : QtRegisterMetaType::None;
@@ -6057,7 +5758,7 @@ QtRegisterMetaType qtMetaTypeRegistration(const AbstractMetaClass *c)
void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const GeneratorContext &context)
{
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
// Gets all class name variants used on different possible scopes
QStringList nameVariants;
if (!context.forSmartPointer())
@@ -6065,7 +5766,7 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const Generato
else
nameVariants << context.preciseType().cppSignature();
- const AbstractMetaClass *enclosingClass = metaClass->enclosingClass();
+ AbstractMetaClassCPtr enclosingClass = metaClass->enclosingClass();
while (enclosingClass) {
if (enclosingClass->typeEntry()->generateCode())
nameVariants << (enclosingClass->name() + u"::"_s + nameVariants.constLast());
@@ -6084,57 +5785,68 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const Generato
case QtRegisterMetaType::None:
break;
case QtRegisterMetaType::Pointer:
- s << "qRegisterMetaType< ::" << className << " *>();\n";
+ s << "qRegisterMetaType< " << m_gsp << className << " *>();\n";
break;
case QtRegisterMetaType::Value:
- for (const QString &name : qAsConst(nameVariants))
- s << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");\n";
+ for (const QString &name : std::as_const(nameVariants))
+ s << "qRegisterMetaType< " << m_gsp << className << " >(\"" << name << "\");\n";
break;
}
for (const AbstractMetaEnum &metaEnum : metaClass->enums()) {
if (!metaEnum.isPrivate() && !metaEnum.isAnonymous()) {
- for (const QString &name : qAsConst(nameVariants)) {
- s << "qRegisterMetaType< ::"
+ for (const QString &name : std::as_const(nameVariants)) {
+ s << "qRegisterMetaType< " << m_gsp
<< metaEnum.typeEntry()->qualifiedCppName() << " >(\""
<< name << "::" << metaEnum.name() << "\");\n";
}
- if (metaEnum.typeEntry()->flags()) {
- QString n = metaEnum.typeEntry()->flags()->originalName();
- s << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");\n";
- }
}
}
}
-void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass,
+ QString *id)
+{
+ if (id->contains("%1"_L1)) {
+ QString replacement = " reinterpret_cast< "_L1 + m_gsp + metaClass->qualifiedCppName()
+ + " *>(cptr)"_L1;
+ id->replace("%1"_L1, replacement);
+ }
+ if (id->contains("%B"_L1)) {
+ auto baseClass = metaClass;
+ while (!baseClass->typeEntry()->isPolymorphicBase() && baseClass->baseClass())
+ baseClass = baseClass->baseClass();
+ QString replacement = " reinterpret_cast< "_L1 + m_gsp + baseClass->qualifiedCppName()
+ + " *>(cptr)"_L1;
+ id->replace("%B"_L1, replacement);
+ }
+}
+
+void CppGenerator::writeTypeDiscoveryFunction(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass)
{
QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue();
s << "static void *" << cpythonBaseName(metaClass)
- << "_typeDiscovery(void *cptr, PyTypeObject *instanceType)\n{\n" << indent;
+ << "_typeDiscovery(void *cptr, PyTypeObject *instanceType)\n{\n" << indent
+ << sbkUnusedVariableCast("cptr")
+ << sbkUnusedVariableCast("instanceType");
if (!polymorphicExpr.isEmpty()) {
- polymorphicExpr = polymorphicExpr.replace(u"%1"_s,
- u" reinterpret_cast< ::"_s
- + metaClass->qualifiedCppName()
- + u" *>(cptr)"_s);
- s << " if (" << polymorphicExpr << ")\n";
- {
- Indentation indent(s);
- s << "return cptr;\n";
- }
+ replacePolymorphicIdPlaceHolders(metaClass, &polymorphicExpr);
+ s << "if (" << polymorphicExpr << ")\n" << indent
+ << "return cptr;\n" << outdent;
} else if (metaClass->isPolymorphic()) {
const auto &ancestors = metaClass->allTypeSystemAncestors();
- for (auto *ancestor : ancestors) {
- if (ancestor->baseClass())
+ for (const auto &ancestor : ancestors) {
+ if (ancestor->baseClass() && !ancestor->typeEntry()->isPolymorphicBase())
continue;
if (ancestor->isPolymorphic()) {
- s << "if (instanceType == Shiboken::SbkType< ::"
- << ancestor->qualifiedCppName() << " >())\n";
- Indentation indent(s);
- s << "return dynamic_cast< ::" << metaClass->qualifiedCppName()
- << " *>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << " *>(cptr));\n";
+ s << "if (instanceType == Shiboken::SbkType< " << m_gsp
+ << ancestor->qualifiedCppName() << " >())\n" << indent
+ << "return dynamic_cast< " << getFullTypeName(metaClass)
+ << " *>(reinterpret_cast< "<< getFullTypeName(ancestor)
+ << " *>(cptr));\n" << outdent;
} else {
qCWarning(lcShiboken).noquote().nospace()
<< metaClass->qualifiedCppName() << " inherits from a non polymorphic type ("
@@ -6147,7 +5859,8 @@ void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaC
s << "return {};\n" << outdent << "}\n\n";
}
-void CppGenerator::writeSetattroDefinition(TextStream &s, const AbstractMetaClass *metaClass) const
+void CppGenerator::writeSetattroDefinition(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass)
{
s << "static int " << ShibokenGenerator::cpythonSetattroFunctionName(metaClass)
<< "(PyObject *self, PyObject *name, PyObject *value)\n{\n" << indent;
@@ -6157,7 +5870,7 @@ void CppGenerator::writeSetattroDefinition(TextStream &s, const AbstractMetaClas
}
}
-inline void CppGenerator::writeSetattroDefaultReturn(TextStream &s)
+void CppGenerator::writeSetattroDefaultReturn(TextStream &s)
{
s << "return PyObject_GenericSetAttr(self, name, value);\n"
<< outdent << "}\n\n";
@@ -6167,7 +5880,7 @@ void CppGenerator::writeSetattroFunction(TextStream &s, AttroCheck attroCheck,
const GeneratorContext &context) const
{
Q_ASSERT(!context.forSmartPointer());
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
writeSetattroDefinition(s, metaClass);
// PYSIDE-1019: Switch tp_dict before doing tp_setattro.
@@ -6177,58 +5890,36 @@ void CppGenerator::writeSetattroFunction(TextStream &s, AttroCheck attroCheck,
// PYSIDE-803: Detect duck-punching; clear cache if a method is set.
if (attroCheck.testFlag(AttroCheckFlag::SetattroMethodOverride)
&& context.useWrapper()) {
- s << "if (value && PyCallable_Check(value)) {\n" << indent
- << "auto plain_inst = " << cpythonWrapperCPtr(metaClass, u"self"_s) << ";\n"
- << "auto inst = dynamic_cast<" << context.wrapperName() << " *>(plain_inst);\n"
- << "if (inst)\n" << indent
+ s << "if (value != nullptr && PyCallable_Check(value) != 0) {\n" << indent
+ << "auto plain_inst = " << cpythonWrapperCPtr(metaClass, PYTHON_SELF_VAR) << ";\n"
+ << "auto *inst = dynamic_cast<" << context.wrapperName() << " *>(plain_inst);\n"
+ << "if (inst != nullptr)\n" << indent
<< "inst->resetPyMethodCache();\n" << outdent << outdent
<< "}\n";
}
if (attroCheck.testFlag(AttroCheckFlag::SetattroQObject)) {
s << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject *>(PySide::Property::getObject(self, name)));\n"
- << "if (!pp.isNull())\n";
- Indentation indent(s);
- s << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);\n";
+ << "if (!pp.isNull())\n" << indent
+ << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);\n"
+ << outdent;
}
if (attroCheck.testFlag(AttroCheckFlag::SetattroUser)) {
auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
FunctionQueryOption::SetAttroFunction);
Q_ASSERT(func);
- s << "{\n";
- {
- Indentation indent(s);
- s << "auto " << CPP_SELF_VAR << " = "
- << cpythonWrapperCPtr(metaClass, u"self"_s) << ";\n";
- writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
- TypeSystem::TargetLangCode, context);
- }
- s << "}\n";
+ s << "{\n" << indent
+ << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, PYTHON_SELF_VAR) << ";\n";
+ writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, context);
+ s << outdent << "}\n";
}
writeSetattroDefaultReturn(s);
}
-static const char smartPtrComment[] =
- "// Try to find the 'name' attribute, by retrieving the PyObject for "
- "the corresponding C++ object held by the smart pointer.\n";
-
-void CppGenerator::writeSmartPointerSetattroFunction(TextStream &s,
- const GeneratorContext &context) const
-{
- Q_ASSERT(context.forSmartPointer());
- writeSetattroDefinition(s, context.metaClass());
- s << smartPtrComment
- << "if (auto *rawObj = PyObject_CallMethod(self, " << SMART_POINTER_GETTER
- << ", 0)) {\n" << indent
- << "if (PyObject_HasAttr(rawObj, name) != 0)\n" << indent
- << "return PyObject_GenericSetAttr(rawObj, name, value);\n" << outdent
- << "Py_DECREF(rawObj);\n" << outdent
- << "}\n";
- writeSetattroDefaultReturn(s);
-}
-
-void CppGenerator::writeGetattroDefinition(TextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeGetattroDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
s << "static PyObject *" << cpythonGetattroFunctionName(metaClass)
<< "(PyObject *self, PyObject *name)\n{\n" << indent;
@@ -6238,10 +5929,10 @@ QString CppGenerator::qObjectGetAttroFunction() const
{
static QString result;
if (result.isEmpty()) {
- auto qobjectClass = AbstractMetaClass::findClass(api().classes(), qObjectT());
+ auto qobjectClass = AbstractMetaClass::findClass(api().classes(), qObjectT);
Q_ASSERT(qobjectClass);
- result = u"PySide::getMetaDataFromQObject("_s
- + cpythonWrapperCPtr(qobjectClass, u"self"_s)
+ result = u"PySide::getHiddenDataFromQObject("_s
+ + cpythonWrapperCPtr(qobjectClass, PYTHON_SELF_VAR)
+ u", self, name)"_s;
}
return result;
@@ -6251,64 +5942,49 @@ void CppGenerator::writeGetattroFunction(TextStream &s, AttroCheck attroCheck,
const GeneratorContext &context) const
{
Q_ASSERT(!context.forSmartPointer());
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
writeGetattroDefinition(s, metaClass);
// PYSIDE-1019: Switch tp_dict before doing tp_getattro.
if (usePySideExtensions())
s << "PySide::Feature::Select(self);\n";
- const QString getattrFunc = usePySideExtensions() && metaClass->isQObject()
+ const QString getattrFunc = usePySideExtensions() && isQObject(metaClass)
? qObjectGetAttroFunction() : u"PyObject_GenericGetAttr(self, name)"_s;
if (attroCheck.testFlag(AttroCheckFlag::GetattroOverloads)) {
s << "// Search the method in the instance dict\n"
<< "auto *ob_dict = SbkObject_GetDict_NoRef(self);\n";
- s << "if (auto *meth = PyDict_GetItem(ob_dict, name)) {\n";
- {
- Indentation indent(s);
- s << "Py_INCREF(meth);\n"
- << "return meth;\n";
- }
- s << "}\n"
+ s << "if (auto *meth = PyDict_GetItem(ob_dict, name)) {\n" << indent
+ << "Py_INCREF(meth);\nreturn meth;\n" << outdent << "}\n"
<< "// Search the method in the type dict\n"
- << "if (Shiboken::Object::isUserType(self)) {\n";
- {
- Indentation indent(s);
- // PYSIDE-772: Perform optimized name mangling.
- s << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));\n"
- << "if (auto *meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp)) {\n";
- {
- Indentation indent(s);
- // PYSIDE-1523: PyFunction_Check is not accepting compiled functions.
- s << "if (strcmp(Py_TYPE(meth)->tp_name, \"compiled_function\") == 0)\n";
- {
- Indentation indent(s);
- s << "return Py_TYPE(meth)->tp_descr_get(meth, self, nullptr);\n";
- }
- s << "return PyFunction_Check(meth) ? PyMethod_New(meth, self)\n"
- << " : " << getattrFunc << ";\n";
- }
- s << "}\n";
- }
- s << "}\n";
+ << "if (Shiboken::Object::isUserType(self)) {\n" << indent;
+ // PYSIDE-772: Perform optimized name mangling.
+ s << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));\n"
+ << "Shiboken::AutoDecRef tpDict(PepType_GetDict(Py_TYPE(self)));\n"
+ << "if (auto *meth = PyDict_GetItem(tpDict.object(), tmp)) {\n" << indent;
+ // PYSIDE-1523: PyFunction_Check is not accepting compiled functions.
+ s << "if (std::strcmp(Py_TYPE(meth)->tp_name, \"compiled_function\") == 0) {\n" << indent
+ << "auto descrGetFunc = "
+ << pyTypeGetSlot("descrgetfunc", "Py_TYPE(meth)", "Py_tp_descr_get") << ";\n"
+ << "return descrGetFunc(meth, self, nullptr);\n" << outdent
+ << "}\nreturn PyFunction_Check(meth) ? PyMethod_New(meth, self)\n"
+ << " : " << getattrFunc << ";\n" << outdent
+ << "}\n" << outdent << "}\n";
const auto &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass);
for (const auto &func : funcs) {
QString defName = cpythonMethodDefinitionName(func);
- s << "static PyMethodDef non_static_" << defName << " = {\n";
- {
- Indentation indent(s);
- s << defName << ".ml_name,\n"
- << defName << ".ml_meth,\n"
- << defName << ".ml_flags & (~METH_STATIC),\n"
- << defName << ".ml_doc,\n";
- }
- s << "};\n"
+ s << "static PyMethodDef non_static_" << defName << " = {\n" << indent
+ << defName << ".ml_name,\n"
+ << defName << ".ml_meth,\n"
+ << defName << ".ml_flags & (~METH_STATIC),\n"
+ << defName << ".ml_doc,\n" << outdent
+ << "};\n"
<< "if (Shiboken::String::compare(name, \""
- << func->definitionNames().constFirst() << "\") == 0)\n";
- Indentation indent(s);
- s << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);\n";
+ << func->definitionNames().constFirst() << "\") == 0)\n" << indent
+ << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);\n"
+ << outdent;
}
}
@@ -6316,64 +5992,17 @@ void CppGenerator::writeGetattroFunction(TextStream &s, AttroCheck attroCheck,
auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
FunctionQueryOption::GetAttroFunction);
Q_ASSERT(func);
- s << "{\n";
- {
- Indentation indent(s);
- s << "auto " << CPP_SELF_VAR << " = "
- << cpythonWrapperCPtr(metaClass, u"self"_s) << ";\n";
- writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
- TypeSystem::TargetLangCode, context);
- }
- s << "}\n";
+ s << "{\n" << indent
+ << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, PYTHON_SELF_VAR) << ";\n";
+ writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, context);
+ s << outdent << "}\n";
}
s << "return " << getattrFunc << ";\n" << outdent << "}\n\n";
}
-void CppGenerator::writeSmartPointerGetattroFunction(TextStream &s,
- const GeneratorContext &context,
- const BoolCastFunctionOptional &boolCast)
-{
- Q_ASSERT(context.forSmartPointer());
- const AbstractMetaClass *metaClass = context.metaClass();
- writeGetattroDefinition(s, metaClass);
- s << "PyObject *tmp = PyObject_GenericGetAttr(self, name);\n"
- << "if (tmp)\n" << indent << "return tmp;\n" << outdent
- << "if (PyErr_ExceptionMatches(PyExc_AttributeError) == 0)\n"
- << indent << "return nullptr;\n" << outdent
- << "PyErr_Clear();\n";
-
- if (boolCast.has_value()) {
- writeSmartPointerCppSelfDefinition(s, context);
- s << "if (";
- writeNbBoolExpression(s, boolCast.value(), true /* invert */);
- s << ") {\n" << indent
- << R"(PyTypeObject *tp = Py_TYPE(self);
-PyErr_Format(PyExc_AttributeError, "Attempt to retrieve '%s' from null object '%s'.",
- Shiboken::String::toCString(name), tp->tp_name);
-return nullptr;
-)" << outdent << "}\n";
- }
-
- // This generates the code which dispatches access to member functions
- // and fields from the smart pointer to its pointee.
- s << smartPtrComment
- << "if (auto *rawObj = PyObject_CallMethod(self, "
- << SMART_POINTER_GETTER << ", 0)) {\n" << indent
- << "if (auto *attribute = PyObject_GetAttr(rawObj, name))\n"
- << indent << "tmp = attribute;\n" << outdent
- << "Py_DECREF(rawObj);\n" << outdent
- << "}\n"
- << "if (!tmp) {\n" << indent
- << R"(PyTypeObject *tp = Py_TYPE(self);
-PyErr_Format(PyExc_AttributeError,
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, Shiboken::String::toCString(name));
-)" << outdent
- << "}\n"
- << "return tmp;\n" << outdent << "}\n\n";
-}
-
void CppGenerator::writeNbBoolExpression(TextStream &s, const BoolCastFunction &f,
bool invert)
{
@@ -6390,7 +6019,7 @@ void CppGenerator::writeNbBoolExpression(TextStream &s, const BoolCastFunction &
void CppGenerator::writeNbBoolFunction(const GeneratorContext &context,
const BoolCastFunction &f,
- TextStream &s) const
+ TextStream &s)
{
s << "static int " << cpythonBaseName(context.metaClass()) << "___nb_bool(PyObject *self)\n"
<< "{\n" << indent;
@@ -6414,28 +6043,53 @@ void CppGenerator::writeNbBoolFunction(const GeneratorContext &context,
// function.
void CppGenerator::writeInitFunc(TextStream &declStr, TextStream &callStr,
const QString &initFunctionName,
- const TypeEntry *enclosingEntry)
+ const TypeEntryCPtr &enclosingEntry,
+ const QString &pythonName, bool lazy)
{
- const bool hasParent =
- enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType;
- declStr << "void init_" << initFunctionName << "(PyObject *"
+ const QString functionName = "init_"_L1 + initFunctionName;
+ const bool hasParent = enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType;
+ declStr << "PyTypeObject *" << functionName << "(PyObject *"
<< (hasParent ? "enclosingClass" : "module") << ");\n";
- callStr << "init_" << initFunctionName;
- if (hasParent) {
- callStr << "(reinterpret_cast<PyTypeObject *>("
- << cpythonTypeNameExt(enclosingEntry) << ")->tp_dict);\n";
+
+ if (!lazy) {
+ const QString enclosing = hasParent
+ ? "reinterpret_cast<PyObject *>("_L1 + cpythonTypeNameExt(enclosingEntry) + u')'
+ : "module"_L1;
+ callStr << functionName << '(' << enclosing << ");\n";
+ } else if (hasParent) {
+ const QString &enclosingName = enclosingEntry->name();
+ const auto parts = QStringView{enclosingName}.split(u"::", Qt::SkipEmptyParts);
+ const QString namePathPrefix = enclosingEntry->name().replace("::"_L1, "."_L1);
+ callStr << "Shiboken::Module::AddTypeCreationFunction("
+ << "module, \"" << parts[0] << "\", "
+ << functionName << ", \"" << namePathPrefix << '.' << pythonName << "\");\n";
} else {
- callStr << "(module);\n";
+ callStr << "Shiboken::Module::AddTypeCreationFunction("
+ << "module, \"" << pythonName << "\", "
+ << functionName << ");\n";
}
}
+static void writeSubModuleHandling(TextStream &s, const QString &moduleName,
+ const QString &subModuleOf)
+{
+ s << "{\n" << indent
+ << "Shiboken::AutoDecRef parentModule(Shiboken::Module::import(\""
+ << subModuleOf << "\"));\n"
+ << "if (parentModule.isNull())\n" << indent
+ << "return nullptr;\n" << outdent
+ << "if (PyModule_AddObject(parentModule.object(), \"" << moduleName
+ << "\", module) < 0)\n"
+ << indent << "return nullptr;\n" << outdent << outdent << "}\n";
+}
+
bool CppGenerator::finishGeneration()
{
//Generate CPython wrapper file
StringStream s_classInitDecl(TextStream::Language::Cpp);
StringStream s_classPythonDefines(TextStream::Language::Cpp);
- QSet<Include> includes;
+ std::set<Include> includes;
StringStream s_globalFunctionImpl(TextStream::Language::Cpp);
StringStream s_globalFunctionDef(TextStream::Language::Cpp);
StringStream signatureStream(TextStream::Language::Cpp);
@@ -6444,8 +6098,8 @@ bool CppGenerator::finishGeneration()
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
const AbstractMetaFunctionCList &overloads = it.value();
for (const auto &func : overloads) {
- if (func->typeEntry())
- includes << func->typeEntry()->include();
+ if (auto te = func->typeEntry())
+ includes.insert(te->include());
}
if (overloads.isEmpty())
@@ -6461,26 +6115,61 @@ bool CppGenerator::finishGeneration()
}
AbstractMetaClassCList classesWithStaticFields;
- for (auto cls : api().classes()){
- auto *te = cls->typeEntry();
+ for (const auto &cls : api().classes()){
+ auto te = cls->typeEntry();
if (shouldGenerate(te)) {
+ const bool hasConfigCondition = te->hasConfigCondition();
+ if (hasConfigCondition) {
+ s_classInitDecl << te->configCondition() << '\n';
+ s_classPythonDefines << te->configCondition() << '\n';
+ }
writeInitFunc(s_classInitDecl, s_classPythonDefines,
getSimpleClassInitFunctionName(cls),
- te->targetLangEnclosingEntry());
+ targetLangEnclosingEntry(te), cls->name());
if (cls->hasStaticFields()) {
- s_classInitDecl << "void "
- << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n";
+ s_classInitDecl << "PyTypeObject *"
+ << getSimpleClassStaticFieldsInitFunctionName(cls) << "(PyObject *module);\n";
classesWithStaticFields.append(cls);
}
+ if (hasConfigCondition) {
+ s_classInitDecl << "#endif\n";
+ s_classPythonDefines << "#endif\n";
+ }
}
}
// Initialize smart pointer types.
for (const auto &smp : api().instantiatedSmartPointers()) {
GeneratorContext context = contextForSmartPointer(smp.specialized, smp.type);
+ const auto enclosingClass = context.metaClass()->enclosingClass();
+ auto enclosingTypeEntry = enclosingClass
+ ? enclosingClass->typeEntry()
+ : targetLangEnclosingEntry(smp.type.typeEntry());
+
writeInitFunc(s_classInitDecl, s_classPythonDefines,
getInitFunctionName(context),
- smp.type.typeEntry()->targetLangEnclosingEntry());
+ enclosingTypeEntry, smp.type.name());
+ includes.insert(smp.type.instantiations().constFirst().typeEntry()->include());
+ }
+
+ for (auto &instantiatedContainer : api().instantiatedContainers()) {
+ includes.insert(instantiatedContainer.typeEntry()->include());
+ for (const auto &inst : instantiatedContainer.instantiations())
+ includes.insert(inst.typeEntry()->include());
+ }
+
+ const ExtendedConverterData extendedConverters = getExtendedConverters();
+ for (auto it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) {
+ TypeEntryCPtr te = it.key();
+ includes.insert(te->include());
+ for (const auto &metaClass : it.value())
+ includes.insert(metaClass->typeEntry()->include());
+ }
+
+ const QList<CustomConversionPtr> &typeConversions = getPrimitiveCustomConversions();
+ for (const auto &c : typeConversions) {
+ if (auto te = c->ownerType())
+ includes.insert(te->include());
}
QString moduleFileName(outputDirectory() + u'/' + subDirectoryForPackage(packageName()));
@@ -6512,55 +6201,64 @@ bool CppGenerator::finishGeneration()
}
s << "#include \"" << getModuleHeaderFileName() << '"' << "\n\n";
- for (const Include &include : qAsConst(includes))
+ for (const Include &include : includes)
s << include;
s << '\n';
// Global enums
AbstractMetaEnumList globalEnums = api().globalEnums();
- for (const AbstractMetaClass *nsp : invisibleTopNamespaces())
+ for (const auto &nsp : invisibleTopNamespaces()) {
+ const auto oldSize = globalEnums.size();
nsp->getEnumsToBeGenerated(&globalEnums);
+ if (globalEnums.size() > oldSize)
+ s << nsp->typeEntry()->include();
+ }
TypeDatabase *typeDb = TypeDatabase::instance();
- const TypeSystemTypeEntry *moduleEntry = typeDb->defaultTypeSystemType();
+ TypeSystemTypeEntryCPtr moduleEntry = typeDb->defaultTypeSystemType();
Q_ASSERT(moduleEntry);
s << '\n';
// Extra includes
QList<Include> extraIncludes = moduleEntry->extraIncludes();
- for (const AbstractMetaEnum &cppEnum : qAsConst(globalEnums))
+ for (const AbstractMetaEnum &cppEnum : std::as_const(globalEnums))
extraIncludes.append(cppEnum.typeEntry()->extraIncludes());
if (!extraIncludes.isEmpty()) {
s << "// Extra includes\n";
std::sort(extraIncludes.begin(), extraIncludes.end());
- for (const Include &inc : qAsConst(extraIncludes))
+ for (const Include &inc : std::as_const(extraIncludes))
s << inc;
s << '\n';
}
+ // FIXME PYSIDE-7: Remove backwards compatible structure
s << "// Current module's type array.\n"
- << "PyTypeObject **" << cppApiVariableName() << " = nullptr;\n"
+ << "Shiboken::Module::TypeInitStruct *" << cppApiVariableName() << " = nullptr;\n"
+ << "// Backwards compatible structure with identical indexing.\n"
+ << "PyTypeObject **" << cppApiVariableNameOld() << " = nullptr;\n"
<< "// Current module's PyObject pointer.\n"
<< "PyObject *" << pythonModuleObjectName() << " = nullptr;\n"
<< "// Current module's converter array.\n"
- << "SbkConverter **" << convertersVariableName() << " = nullptr;\n";
+ << "SbkConverter **" << convertersVariableName() << " = nullptr;\n\n";
const CodeSnipList snips = moduleEntry->codeSnips();
// module inject-code native/beginning
- if (!snips.isEmpty())
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode);
+ writeModuleCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode);
// cleanup staticMetaObject attribute
if (usePySideExtensions()) {
+ QString iType = cppApiVariableName() + "[i].type"_L1;
+ QString iName = cppApiVariableName() + "[i].fullName"_L1;
+
s << "void cleanTypesAttributes() {\n" << indent
<< "static PyObject *attrName = Shiboken::PyName::qtStaticMetaObject();\n"
- << "for (int i = 0, imax = SBK_" << moduleName()
- << "_IDX_COUNT; i < imax; i++) {\n" << indent
- << "PyObject *pyType = reinterpret_cast<PyObject *>(" << cppApiVariableName() << "[i]);\n"
- << "if (pyType && PyObject_HasAttr(pyType, attrName))\n" << indent
+ << "const int imax = SBK_" << moduleName() << "_IDX_COUNT;\n"
+ << "for (int i = 0; i < imax && " << iName << " != nullptr; ++i) {\n" << indent
+ << "auto *pyType = reinterpret_cast<PyObject *>(" << iType << ");\n"
+ << "if (pyType != nullptr && PyObject_HasAttr(pyType, attrName))\n" << indent
<< "PyObject_SetAttr(pyType, attrName, Py_None);\n" << outdent
- << outdent << "}\n" << outdent << "}\n";
+ << outdent << "}\n" << outdent << "}\n\n";
}
s << "// Global functions "
@@ -6568,7 +6266,7 @@ bool CppGenerator::finishGeneration()
<< s_globalFunctionImpl.toString() << '\n'
<< "static PyMethodDef " << moduleName() << "_methods[] = {\n" << indent
<< s_globalFunctionDef.toString()
- << "{0} // Sentinel\n" << outdent << "};\n\n"
+ << METHOD_DEF_SENTINEL << outdent << "};\n\n"
<< "// Classes initialization functions "
<< "------------------------------------------------------------\n"
<< s_classInitDecl.toString() << '\n';
@@ -6578,12 +6276,8 @@ bool CppGenerator::finishGeneration()
s << "// Enum definitions "
<< "------------------------------------------------------------\n";
- for (const AbstractMetaEnum &cppEnum : qAsConst(globalEnums)) {
- if (cppEnum.isAnonymous() || cppEnum.isPrivate())
- continue;
+ for (const AbstractMetaEnum &cppEnum : std::as_const(globalEnums))
writeEnumConverterFunctions(s, cppEnum);
- s << '\n';
- }
if (convImpl.size() > 0) {
s << "// Enum converters "
@@ -6593,7 +6287,6 @@ bool CppGenerator::finishGeneration()
<< "} // namespace Shiboken\n\n";
}
- writeFlagsNumberMethodsDefinitions(s, globalEnums);
s << '\n';
}
@@ -6601,20 +6294,19 @@ bool CppGenerator::finishGeneration()
if (!requiredModules.isEmpty())
s << "// Required modules' type and converter arrays.\n";
for (const QString &requiredModule : requiredModules) {
- s << "PyTypeObject **" << cppApiVariableName(requiredModule) << ";\n"
+ s << "Shiboken::Module::TypeInitStruct *" << cppApiVariableName(requiredModule) << ";\n"
<< "SbkConverter **" << convertersVariableName(requiredModule) << ";\n";
}
s << "\n// Module initialization "
<< "------------------------------------------------------------\n";
- ExtendedConverterData extendedConverters = getExtendedConverters();
if (!extendedConverters.isEmpty()) {
s << '\n' << "// Extended Converters.\n\n";
for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) {
- const TypeEntry *externalType = it.key();
+ TypeEntryCPtr externalType = it.key();
s << "// Extended implicit conversions for "
<< externalType->qualifiedTargetLangName() << '.' << '\n';
- for (const AbstractMetaClass *sourceClass : it.value()) {
+ for (const auto &sourceClass : it.value()) {
AbstractMetaType sourceType = AbstractMetaType::fromAbstractMetaClass(sourceClass);
AbstractMetaType targetType = AbstractMetaType::fromTypeEntry(externalType);
writePythonToCppConversionFunctions(s, sourceType, targetType);
@@ -6622,10 +6314,9 @@ bool CppGenerator::finishGeneration()
}
}
- const QList<const CustomConversion *> &typeConversions = getPrimitiveCustomConversions();
if (!typeConversions.isEmpty()) {
s << "\n// Primitive Type converters.\n\n";
- for (const CustomConversion *conversion : typeConversions) {
+ for (const auto &conversion : typeConversions) {
s << "// C++ to Python conversion for primitive type '" << conversion->ownerType()->qualifiedCppName() << "'.\n";
writeCppToPythonFunction(s, conversion);
writeCustomConverterFunctions(s, conversion);
@@ -6635,14 +6326,17 @@ bool CppGenerator::finishGeneration()
QHash<AbstractMetaType, OpaqueContainerData> opaqueContainers;
const auto &containers = api().instantiatedContainers();
+ QSet<AbstractMetaType> valueConverters;
if (!containers.isEmpty()) {
s << "// Container Type converters.\n\n";
for (const AbstractMetaType &container : containers) {
- s << "// C++ to Python conversion for container type '" << container.cppSignature() << "'.\n";
+ s << "// C++ to Python conversion for container type '"
+ << container.cppSignature() << "'.\n";
writeContainerConverterFunctions(s, container);
if (container.generateOpaqueContainer()) {
- opaqueContainers.insert(container,
- writeOpaqueContainerConverterFunctions(s, container));
+ auto data = writeOpaqueContainerConverterFunctions(s, container,
+ &valueConverters);
+ opaqueContainers.insert(container, data);
}
}
s << '\n';
@@ -6674,6 +6368,8 @@ bool CppGenerator::finishGeneration()
// PYSIDE-510: Create a signatures string for the introspection feature.
writeSignatureStrings(s, signatureStream.toString(), moduleName(), "global functions");
+ writeInitInheritance(s);
+
// Write module init function
const QString globalModuleVar = pythonModuleObjectName();
s << "extern \"C\" LIBSHIBOKEN_EXPORT PyObject *PyInit_"
@@ -6683,8 +6379,8 @@ bool CppGenerator::finishGeneration()
<< indent << "return " << globalModuleVar << ";\n" << outdent;
// module inject-code target/beginning
- if (!snips.isEmpty())
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode);
+ writeModuleCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning,
+ TypeSystem::TargetLangCode);
for (const QString &requiredModule : requiredModules) {
s << "{\n" << indent
@@ -6700,9 +6396,25 @@ bool CppGenerator::finishGeneration()
int maxTypeIndex = getMaxTypeIndex() + api().instantiatedSmartPointers().size();
if (maxTypeIndex) {
- s << "// Create an array of wrapper types for the current module.\n"
- << "static PyTypeObject *cppApi[SBK_" << moduleName() << "_IDX_COUNT];\n"
- << cppApiVariableName() << " = cppApi;\n\n";
+ s << "// Create an array of wrapper types/names for the current module.\n"
+ << "static Shiboken::Module::TypeInitStruct cppApi[] = {\n" << indent;
+
+ // Windows did not like an array of QString.
+ QStringList typeNames;
+ for (int idx = 0; idx < maxTypeIndex; ++idx)
+ typeNames.append("+++ unknown entry #"_L1 + QString::number(idx)
+ + " in "_L1 + moduleName());
+
+ collectFullTypeNamesArray(typeNames);
+
+ for (auto typeName : typeNames)
+ s << "{nullptr, \"" << typeName << "\"},\n";
+
+ s << "{nullptr, nullptr}\n" << outdent << "};\n"
+ << "// The new global structure consisting of (type, name) pairs.\n"
+ << cppApiVariableName() << " = cppApi;\n"
+ << "// The backward compatible alias with upper case indexes.\n"
+ << cppApiVariableNameOld() << " = reinterpret_cast<PyTypeObject **>(cppApi);\n\n";
}
s << "// Create an array of primitive type converters for the current module.\n"
@@ -6712,13 +6424,18 @@ bool CppGenerator::finishGeneration()
<< "PyObject *module = Shiboken::Module::create(\"" << moduleName()
<< "\", &moduledef);\n\n"
<< "// Make module available from global scope\n"
- << globalModuleVar << " = module;\n\n"
- << "// Initialize classes in the type system\n"
+ << globalModuleVar << " = module;\n\n";
+
+ const QString subModuleOf = typeDb->defaultTypeSystemType()->subModuleOf();
+ if (!subModuleOf.isEmpty())
+ writeSubModuleHandling(s, moduleName(), subModuleOf);
+
+ s << "// Initialize classes in the type system\n"
<< s_classPythonDefines.toString();
if (!typeConversions.isEmpty()) {
s << '\n';
- for (const CustomConversion *conversion : typeConversions) {
+ for (const auto &conversion : typeConversions) {
writePrimitiveConverterInitialization(s, conversion);
s << '\n';
}
@@ -6727,7 +6444,7 @@ bool CppGenerator::finishGeneration()
if (!containers.isEmpty()) {
s << '\n';
for (const AbstractMetaType &container : containers) {
- const QString converterObj = writeContainerConverterInitialization(s, container);
+ const QString converterObj = writeContainerConverterInitialization(s, container, api());
const auto it = opaqueContainers.constFind(container);
if (it != opaqueContainers.constEnd()) {
writeSetPythonToCppPointerConversion(s, converterObj,
@@ -6762,24 +6479,17 @@ bool CppGenerator::finishGeneration()
}
}
- writeEnumsInitialization(s, globalEnums, ErrorReturn::Default);
+ writeEnumsInitialization(s, globalEnums);
s << "// Register primitive types converters.\n";
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *pte : primitiveTypeList) {
- if (!pte->generateCode() || !pte->isCppPrimitive())
+ const PrimitiveTypeEntryCList &primitiveTypeList = primitiveTypes();
+ for (const auto &pte : primitiveTypeList) {
+ if (!pte->generateCode() || !isCppPrimitive(pte))
continue;
if (!pte->referencesType())
continue;
- const TypeEntry *referencedType = pte->basicReferencedTypeEntry();
- QString converter = converterObject(referencedType);
- QStringList cppSignature = pte->qualifiedCppName().split(u"::"_s, Qt::SkipEmptyParts);
- while (!cppSignature.isEmpty()) {
- QString signature = cppSignature.join(u"::"_s);
- s << "Shiboken::Conversions::registerConverterName("
- << converter << ", \"" << signature << "\");\n";
- cppSignature.removeFirst();
- }
+ TypeEntryCPtr referencedType = basicReferencedTypeEntry(pte);
+ registerConverterInScopes(s, pte->qualifiedCppName(), converterObject(referencedType));
}
s << '\n';
@@ -6791,27 +6501,29 @@ bool CppGenerator::finishGeneration()
// of the previously registered types (PYSIDE-1529).
if (!classesWithStaticFields.isEmpty()) {
s << "\n// Static field initialization\n";
- for (auto cls : qAsConst(classesWithStaticFields))
- s << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n";
+ for (const auto &cls : std::as_const(classesWithStaticFields)) {
+ ConfigurableScope configScope(s, cls->typeEntry());
+ s << getSimpleClassStaticFieldsInitFunctionName(cls) << "(module);\n";
+ }
}
- s << "\nif (PyErr_Occurred()) {\n" << indent
+ s << '\n' << initInheritanceFunction << "();\n"
+ << "\nif (" << shibokenErrorsOccurred << ") {\n" << indent
<< "PyErr_Print();\n"
<< "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n"
<< outdent << "}\n";
// module inject-code target/end
- if (!snips.isEmpty())
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode);
+ writeModuleCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode);
// module inject-code native/end
- if (!snips.isEmpty())
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode);
+ writeModuleCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode);
if (usePySideExtensions()) {
- for (const AbstractMetaEnum &metaEnum : qAsConst(globalEnums))
+ for (const AbstractMetaEnum &metaEnum : std::as_const(globalEnums))
if (!metaEnum.isAnonymous()) {
- s << "qRegisterMetaType< ::" << metaEnum.typeEntry()->qualifiedCppName()
+ ConfigurableScope configScope(s, metaEnum.typeEntry());
+ s << "qRegisterMetaType< " << getFullTypeName(metaEnum.typeEntry())
<< " >(\"" << metaEnum.name() << "\");\n";
}
@@ -6819,7 +6531,7 @@ bool CppGenerator::finishGeneration()
s << "PySide::registerCleanupFunction(cleanTypesAttributes);\n\n";
}
- // finish the rest of __signature__ initialization.
+ // finish the rest of get_signature() initialization.
s << "FinishSignatureInitialization(module, " << moduleName()
<< "_SignatureStrings);\n"
<< "\nreturn module;\n" << outdent << "}\n";
@@ -6845,17 +6557,17 @@ static bool useParentHeuristics(const ApiExtractorResult &api,
{
if (!ComplexTypeEntry::isParentManagementEnabled()) // FIXME PYSIDE 7: Remove this
return true;
- auto *owner = func->ownerClass();
- if (owner == nullptr)
+ const auto owner = func->ownerClass();
+ if (!owner)
return false;
- auto *ownerEntry = owner->parentManagementEntry();
- if (ownerEntry == nullptr)
+ auto ownerEntry = parentManagementEntry(owner);
+ if (!ownerEntry)
return false;
- auto *argTypeEntry = argType.typeEntry();
+ auto argTypeEntry = argType.typeEntry();
if (!argTypeEntry->isComplex())
return false;
- auto *argClass = AbstractMetaClass::findClass(api.classes(), argTypeEntry);
- return argClass != nullptr && argClass->parentManagementEntry() == ownerEntry;
+ const auto argClass = AbstractMetaClass::findClass(api.classes(), argTypeEntry);
+ return argClass && parentManagementEntry(argClass) == ownerEntry;
}
bool CppGenerator::writeParentChildManagement(TextStream &s, const AbstractMetaFunctionCPtr &func,
@@ -6894,7 +6606,7 @@ bool CppGenerator::writeParentChildManagement(TextStream &s, const AbstractMetaF
if (parentIndex == 0) {
parentVariable = PYTHON_RETURN_VAR;
} else if (parentIndex == -1) {
- parentVariable = u"self"_s;
+ parentVariable = PYTHON_SELF_VAR;
} else {
parentVariable = usePyArgs
? pythonArgsAt(parentIndex - 1) : PYTHON_ARG;
@@ -6904,7 +6616,7 @@ bool CppGenerator::writeParentChildManagement(TextStream &s, const AbstractMetaF
if (childIndex == 0) {
childVariable = PYTHON_RETURN_VAR;
} else if (childIndex == -1) {
- childVariable = u"self"_s;
+ childVariable = PYTHON_SELF_VAR;
} else {
childVariable = usePyArgs
? pythonArgsAt(childIndex - 1) : PYTHON_ARG;
@@ -6961,9 +6673,9 @@ void CppGenerator::writeReturnValueHeuristics(TextStream &s, const AbstractMetaF
}
}
-void CppGenerator::writeHashFunction(TextStream &s, const GeneratorContext &context) const
+void CppGenerator::writeHashFunction(TextStream &s, const GeneratorContext &context)
{
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
const char hashType[] = "Py_hash_t";
s << "static " << hashType << ' ' << cpythonBaseName(metaClass)
<< "_HashFunc(PyObject *self)\n{\n" << indent;
@@ -6987,7 +6699,7 @@ void CppGenerator::writeHashFunction(TextStream &s, const GeneratorContext &cont
void CppGenerator::writeDefaultSequenceMethods(TextStream &s,
const GeneratorContext &context) const
{
- const AbstractMetaClass *metaClass = context.metaClass();
+ const auto metaClass = context.metaClass();
ErrorReturn errorReturn = ErrorReturn::Zero;
// __len__
@@ -7054,14 +6766,20 @@ void CppGenerator::writeIndexError(TextStream &s, const QString &errorMsg,
<< errorReturn << outdent << "}\n";
}
+QString CppGenerator::writeReprFunctionHeader(TextStream &s, const GeneratorContext &context)
+{
+ QString funcName = cpythonBaseName(context.metaClass()) + REPR_FUNCTION;
+ s << "extern \"C\"\n{\n"
+ << "static PyObject *" << funcName << "(PyObject *self)\n{\n" << indent;
+ return funcName;
+}
+
QString CppGenerator::writeReprFunction(TextStream &s,
const GeneratorContext &context,
- uint indirections) const
+ uint indirections)
{
- const AbstractMetaClass *metaClass = context.metaClass();
- QString funcName = cpythonBaseName(metaClass) + reprFunction();
- s << "extern \"C\"\n{\n"
- << "static PyObject *" << funcName << "(PyObject *self)\n{\n" << indent;
+ const auto metaClass = context.metaClass();
+ QString funcName = writeReprFunctionHeader(s, context);
writeCppSelfDefinition(s, context);
s << R"(QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
@@ -7075,25 +6793,22 @@ QByteArray str = buffer.data();
const auto idx = str.indexOf('(');
auto *typeName = Py_TYPE(self)->tp_name;
if (idx >= 0)
-)";
- {
- Indentation indent(s);
- s << "str.replace(0, idx, typeName);\n";
- }
- s << "str = str.trimmed();\n"
- << "PyObject *mod = PyDict_GetItem(Py_TYPE(self)->tp_dict, Shiboken::PyMagicName::module());\n";
+)" << indent << "str.replace(0, idx, typeName);\n" << outdent
+ << "str = str.trimmed();\n"
+ << "Shiboken::AutoDecRef tpDict(PepType_GetDict(Py_TYPE(self)));\n"
+ << "PyObject *mod = PyDict_GetItem(tpDict.object(), Shiboken::PyMagicName::module());\n";
// PYSIDE-595: The introduction of heap types has the side effect that the module name
// is always prepended to the type name. Therefore the strchr check:
- s << "if (mod != nullptr && std::strchr(typeName, '.') == nullptr)\n";
- {
- Indentation indent(s);
- s << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);\n";
- }
- s << "else\n";
- {
- Indentation indent(s);
- s << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);\n";
- }
- s << outdent << "}\n} // extern C\n\n";
+ s << "if (mod != nullptr && std::strchr(typeName, '.') == nullptr)\n" << indent
+ << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\","
+ " Shiboken::String::toCString(mod), str.constData(), self);\n"
+ << outdent
+ << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);\n";
+ writeReprFunctionFooter(s);
return funcName;
}
+
+void CppGenerator::writeReprFunctionFooter(TextStream &s)
+{
+ s << outdent << "}\n} // extern C\n\n";
+}
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index a989fe35f..a31c2ca14 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -5,12 +5,15 @@
#define CPPGENERATOR_H
#include "shibokengenerator.h"
-#include "abstractmetalang_enums.h"
#include "include.h"
-#include "modifications.h"
+#include "modifications_typedefs.h"
#include <QtCore/QFlags>
-#include <QtCore/QSharedPointer>
+#include <QtCore/QSet>
+#include <QtCore/QHash>
+
+#include <memory>
+#include <utility>
class OverloadDataNode;
class OverloadDataRootNode;
@@ -42,19 +45,16 @@ public:
protected:
QString fileNameForContext(const GeneratorContext &context) const override;
- static QList<AbstractMetaFunctionCList>
- filterGroupedOperatorFunctions(const AbstractMetaClass *metaClass,
- OperatorQueryOptions query);
void generateClass(TextStream &s, const GeneratorContext &classContext) override;
bool finishGeneration() override;
private:
- struct BoolCastFunction
+ struct VirtualMethodReturn
{
- AbstractMetaFunctionCPtr function;
- bool invert = false; // Function is isNull() (invert result).
+ QString statement;
+ bool needsReference = false;
};
- using BoolCastFunctionOptional = std::optional<BoolCastFunction>;
+
void generateSmartPointerClass(TextStream &s, const GeneratorContext &classContext);
void generateIncludes(TextStream &s, const GeneratorContext &classContext,
@@ -62,41 +62,53 @@ private:
const AbstractMetaClassCList &innerClasses = {}) const;
static void writeInitFunc(TextStream &declStr, TextStream &callStr,
const QString &initFunctionName,
- const TypeEntry *enclosingEntry = nullptr);
+ const TypeEntryCPtr &enclosingEntry,
+ const QString &pythonName, bool lazy = true);
static void writeCacheResetNative(TextStream &s, const GeneratorContext &classContext);
void writeConstructorNative(TextStream &s, const GeneratorContext &classContext,
const AbstractMetaFunctionCPtr &func) const;
- void writeDestructorNative(TextStream &s, const GeneratorContext &classContext) const;
+ static void writeDestructorNative(TextStream &s, const GeneratorContext &classContext);
QString getVirtualFunctionReturnTypeName(const AbstractMetaFunctionCPtr &func) const;
- static QPair<QString, QChar>
- virtualMethodNativeArg(const AbstractMetaFunctionCPtr &func,
+ static std::pair<QString, QChar> virtualMethodNativeArg(const AbstractMetaFunctionCPtr &func,
const AbstractMetaArgument &arg);
- void writeVirtualMethodNativeArgs(TextStream &s,
- const AbstractMetaFunctionCPtr &func,
- const AbstractMetaArgumentList &arguments,
- const QList<int> &invalidateArgs) const;
- void writeVirtualMethodNative(TextStream &s, const AbstractMetaFunctionCPtr &func,
+ static void writeVirtualMethodNativeVectorCallArgs(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaArgumentList &arguments,
+ const QList<int> &invalidateArgs);
+ static void writeVirtualMethodNativeArgs(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaArgumentList &arguments,
+ const QList<int> &invalidateArgs);
+ void writeVirtualMethodNative(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
int cacheIndex) const;
+ void writeVirtualMethodPythonOverride(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const CodeSnipList &snips,
+ const VirtualMethodReturn &returnStatement) const;
+ void writeUserAddedPythonOverride(TextStream &s,
+ const AbstractMetaFunctionCPtr &func) const;
void writeVirtualMethodCppCall(TextStream &s, const AbstractMetaFunctionCPtr &func,
const QString &funcName, const QList<CodeSnip> &snips,
- const AbstractMetaArgument *lastArg, const TypeEntry *retType,
- const QString &returnStatement) const;
- static QString virtualMethodReturn(TextStream &s, const ApiExtractorResult &api,
- const AbstractMetaFunctionCPtr &func,
- const FunctionModificationList &functionModifications);
+ const AbstractMetaArgument *lastArg, const TypeEntryCPtr &retType,
+ const QString &returnStatement, bool hasGil) const;
+
+ static VirtualMethodReturn virtualMethodReturn(const ApiExtractorResult &api,
+ const AbstractMetaFunctionCPtr &func,
+ const FunctionModificationList &functionModifications);
void writeMetaObjectMethod(TextStream &s, const GeneratorContext &classContext) const;
static void writeMetaCast(TextStream &s, const GeneratorContext &classContext);
- void writeEnumConverterFunctions(TextStream &s, const TypeEntry *enumType) const;
void writeEnumConverterFunctions(TextStream &s, const AbstractMetaEnum &metaEnum) const;
- void writeConverterFunctions(TextStream &s, const AbstractMetaClass *metaClass,
+ void writeConverterFunctions(TextStream &s, const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext) const;
void writeCustomConverterFunctions(TextStream &s,
- const CustomConversion *customConversion) const;
- void writeConverterRegister(TextStream &s, const AbstractMetaClass *metaClass,
+ const CustomConversionPtr &customConversion) const;
+ void writeConverterRegister(TextStream &s, const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext) const;
- static void writeCustomConverterRegister(TextStream &s, const CustomConversion *customConversion,
+ static void writeCustomConverterRegister(TextStream &s,
+ const CustomConversionPtr &customConversion,
const QString &converterVar);
void writeContainerConverterFunctions(TextStream &s,
@@ -113,16 +125,21 @@ private:
OpaqueContainerData
writeOpaqueContainerConverterFunctions(TextStream &s,
- const AbstractMetaType &containerType) const;
+ const AbstractMetaType &containerType,
+ QSet<AbstractMetaType> *valueTypes) const;
+ void writeOpaqueContainerValueConverter(TextStream &s,
+ const AbstractMetaType &valueType) const;
void writeSmartPointerConverterFunctions(TextStream &s,
const AbstractMetaType &smartPointerType) const;
- bool needsArgumentErrorHandling(const OverloadData &overloadData) const;
- void writeMethodWrapperPreamble(TextStream &s, const OverloadData &overloadData,
- const GeneratorContext &context,
- ErrorReturn errorReturn = ErrorReturn::Default) const;
- void writeConstructorWrapper(TextStream &s, const OverloadData &overloadData,
+ static bool needsArgumentErrorHandling(const OverloadData &overloadData);
+ static void writeMethodWrapperPreamble(TextStream &s,
+ const OverloadData &overloadData,
+ const GeneratorContext &context,
+ ErrorReturn errorReturn = ErrorReturn::Default);
+ void writeConstructorWrapper(TextStream &s,
+ const OverloadData &overloadData,
const GeneratorContext &classContext) const;
void writeMethodWrapper(TextStream &s, const OverloadData &overloadData,
const GeneratorContext &classContext) const;
@@ -138,22 +155,29 @@ private:
bool useWrapperClass);
static void writeSmartPointerCppSelfConversion(TextStream &s,
const GeneratorContext &context);
+
+ static void writeCppSelfVarDef(TextStream &s, CppSelfDefinitionFlags flags = {});
static void writeSmartPointerCppSelfDefinition(TextStream &s,
const GeneratorContext &,
ErrorReturn errorReturn = ErrorReturn::Default,
CppSelfDefinitionFlags flags = {});
- void writeCppSelfDefinition(TextStream &s,
- const AbstractMetaFunctionCPtr &func,
- const GeneratorContext &context,
- ErrorReturn errorReturn = ErrorReturn::Default,
- CppSelfDefinitionFlags flags = {}) const;
- void writeCppSelfDefinition(TextStream &s,
- const GeneratorContext &context,
- ErrorReturn errorReturn = ErrorReturn::Default,
- CppSelfDefinitionFlags flags = {}) const;
-
- static void writeErrorSection(TextStream &s, const OverloadData &overloadData,
+ static void writeCppSelfDefinition(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ const GeneratorContext &context,
+ ErrorReturn errorReturn = ErrorReturn::Default,
+ CppSelfDefinitionFlags flags = {});
+ static void writeCppSelfDefinition(TextStream &s,
+ const GeneratorContext &context,
+ ErrorReturn errorReturn = ErrorReturn::Default,
+ CppSelfDefinitionFlags flags = {});
+
+ static void writeErrorSection(TextStream &s,
+ const OverloadData &overloadData,
ErrorReturn errorReturn);
+
+ static QString returnErrorWrongArguments(const OverloadData &overloadData,
+ ErrorReturn errorReturn);
+
static void writeFunctionReturnErrorCheckSection(TextStream &s,
ErrorReturn errorReturn,
bool hasReturnValue = true);
@@ -167,18 +191,22 @@ private:
bool isNumber = false, bool rejectNull = false);
static void writeTypeCheck(TextStream &s, const QString &customType,
const QString &argumentName);
- static void writeTypeCheck(TextStream& s, const QSharedPointer<OverloadDataNode> &overloadData,
+ static void writeTypeCheck(TextStream& s, const std::shared_ptr<OverloadDataNode> &overloadData,
const QString &argumentName);
- static void writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClass *metaClass);
+ static void replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass,
+ QString *id);
+ static void writeTypeDiscoveryFunction(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass);
- void writeSetattroDefinition(TextStream &s, const AbstractMetaClass *metaClass) const;
+ static void writeSetattroDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass);
static void writeSetattroDefaultReturn(TextStream &s);
- void writeSmartPointerSetattroFunction(TextStream &s,
- const GeneratorContext &context) const;
- void writeSetattroFunction(TextStream &s, AttroCheck attroCheck,
+ static void writeSmartPointerSetattroFunction(TextStream &s,
+ const GeneratorContext &context);
+ void writeSetattroFunction(TextStream &s,
+ AttroCheck attroCheck,
const GeneratorContext &context) const;
- static void writeGetattroDefinition(TextStream &s, const AbstractMetaClass *metaClass);
+ static void writeGetattroDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass);
static void writeSmartPointerGetattroFunction(TextStream &s,
const GeneratorContext &context,
const BoolCastFunctionOptional &boolCast);
@@ -186,11 +214,10 @@ private:
const GeneratorContext &context) const;
QString qObjectGetAttroFunction() const;
- void writeNbBoolFunction(const GeneratorContext &context,
- const BoolCastFunction &f,
- TextStream &s) const;
- static void writeNbBoolExpression(TextStream &s, const BoolCastFunction &f,
- bool invert = false);
+ static void writeNbBoolFunction(const GeneratorContext &context,
+ const BoolCastFunction &f,
+ TextStream &s);
+ static void writeNbBoolExpression(TextStream &s, const BoolCastFunction &f, bool invert = false);
/**
* Writes Python to C++ conversions for arguments on Python wrappers.
@@ -204,12 +231,12 @@ private:
* \param defaultValue an optional default value to be used instead of the conversion result
* \param castArgumentAsUnused if true the converted argument is cast as unused to avoid compiler warnings
*/
- void writeArgumentConversion(TextStream &s, const AbstractMetaType &argType,
- const QString &argName, const QString &pyArgName,
- ErrorReturn errorReturn,
- const AbstractMetaClass *context = nullptr,
- const QString &defaultValue = QString(),
- bool castArgumentAsUnused = false) const;
+ qsizetype writeArgumentConversion(TextStream &s, const AbstractMetaType &argType,
+ const QString &argName, const QString &pyArgName,
+ ErrorReturn errorReturn,
+ const AbstractMetaClassCPtr &context = {},
+ const QString &defaultValue = QString(),
+ bool castArgumentAsUnused = false) const;
/**
* Returns the AbstractMetaType for a function argument.
@@ -229,7 +256,7 @@ private:
const AbstractMetaType &type,
const QString &pyIn,
const QString &cppOut,
- const AbstractMetaClass *context = nullptr,
+ const AbstractMetaClassCPtr &context = {},
const QString &defaultValue = {}) const;
/// Writes the conversion rule for arguments of regular and virtual methods.
@@ -257,7 +284,8 @@ private:
* \param s text stream to write
* \param overloadData the overload data describing all the possible overloads for the function/method
*/
- void writeOverloadedFunctionDecisor(TextStream &s, const OverloadData &overloadData) const;
+ void writeOverloadedFunctionDecisor(TextStream &s, const OverloadData &overloadData,
+ ErrorReturn errorReturn) const;
/// Recursive auxiliar method to the other writeOverloadedFunctionDecisor.
void writeOverloadedFunctionDecisorEngine(TextStream &s,
const OverloadData &overloadData,
@@ -282,18 +310,22 @@ private:
/// Returns the name of a Python to C++ conversion function.
static QString pythonToCppFunctionName(const QString &sourceTypeName, const QString &targetTypeName);
static QString pythonToCppFunctionName(const AbstractMetaType &sourceType, const AbstractMetaType &targetType);
- static QString pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion *toNative, const TypeEntry *targetType);
+ static QString pythonToCppFunctionName(const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType);
/// Returns the name of a Python to C++ convertible check function.
static QString convertibleToCppFunctionName(const QString &sourceTypeName, const QString &targetTypeName);
static QString convertibleToCppFunctionName(const AbstractMetaType &sourceType, const AbstractMetaType &targetType);
- static QString convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion *toNative, const TypeEntry *targetType);
+ static QString convertibleToCppFunctionName(const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType);
/// Writes a C++ to Python conversion function.
void writeCppToPythonFunction(TextStream &s, const QString &code, const QString &sourceTypeName,
QString targetTypeName = QString()) const;
- void writeCppToPythonFunction(TextStream &s, const CustomConversion *customConversion) const;
+ void writeCppToPythonFunction(TextStream &s, const CustomConversionPtr &customConversion) const;
void writeCppToPythonFunction(TextStream &s, const AbstractMetaType &containerType) const;
+ /// Main target type name of a container (for naming the functions).
+ static QString containerNativeToTargetTypeName(const ContainerTypeEntryCPtr &type);
/// Writes a Python to C++ conversion function.
void writePythonToCppFunction(TextStream &s, const QString &code, const QString &sourceTypeName,
@@ -316,13 +348,17 @@ private:
const QString &preConversion = QString()) const;
/// Writes a pair of Python to C++ conversion and check functions for implicit conversions.
void writePythonToCppConversionFunctions(TextStream &s,
- const CustomConversion::TargetToNativeConversion *toNative,
- const TypeEntry *targetType) const;
+ const TargetToNativeConversion &toNative,
+ const TypeEntryCPtr &targetType) const;
/// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
void writePythonToCppConversionFunctions(TextStream &s,
const AbstractMetaType &containerType) const;
+ void writePythonToCppConversionFunction(TextStream &s,
+ const AbstractMetaType &containerType,
+ const TargetToNativeConversion &conv) const;
+
static void writeAddPythonToCppConversion(TextStream &s, const QString &converterVar,
const QString &pythonToCppFunc,
const QString &isConvertibleFunc);
@@ -331,39 +367,46 @@ private:
const QString &pythonToCppFunc,
const QString &isConvertibleFunc);
- static void writeNamedArgumentResolution(TextStream &s, const AbstractMetaFunctionCPtr &func,
- bool usePyArgs, const OverloadData &overloadData);
+ static void writeNamedArgumentResolution(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ bool usePyArgs,
+ const OverloadData &overloadData,
+ ErrorReturn errorReturn);
/// Returns a string containing the name of an argument for the given function and argument index.
static QString argumentNameFromIndex(const ApiExtractorResult &api,
const AbstractMetaFunctionCPtr &func, int argIndex);
/// Returns the class for an ownership modification of the argument.
/// Throws if the argument is not a class or cannot be found.
- static const AbstractMetaClass *
+ static AbstractMetaClassCPtr
argumentClassFromIndex(const ApiExtractorResult &api,
const AbstractMetaFunctionCPtr &func, int argIndex);
void writeMethodCall(TextStream &s, const AbstractMetaFunctionCPtr &func,
const GeneratorContext &context, bool usesPyArgs,
- int maxArgs, ErrorReturn errorReturn) const;
+ int maxArgs, const QList<qsizetype> &argumentIndirections,
+ ErrorReturn errorReturn) const;
static QString getInitFunctionName(const GeneratorContext &context) ;
- static QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) ;
- static QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass);
+ static QString getSimpleClassInitFunctionName(const AbstractMetaClassCPtr &metaClass);
+ static QString
+ getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClassCPtr &metaClass);
static void writeSignatureStrings(TextStream &s, const QString &signatures,
const QString &arrayName,
const char *comment);
+ void writeInitInheritance(TextStream &s) const;
void writeClassRegister(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext,
const QString &signatures) const;
- QString destructorClassName(const AbstractMetaClass *metaClass,
- const GeneratorContext &classContext) const;
+ static QStringList pyBaseTypes(const AbstractMetaClassCPtr &metaClass);
+ static QString destructorClassName(const AbstractMetaClassCPtr &metaClass,
+ const GeneratorContext &classContext);
static void writeStaticFieldInitialization(TextStream &s,
- const AbstractMetaClass *metaClass);
+ const AbstractMetaClassCPtr &metaClass);
void writeClassDefinition(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &classContext);
QByteArrayList methodDefinitionParameters(const OverloadData &overloadData) const;
QList<PyMethodDefEntry> methodDefinitionEntries(const OverloadData &overloadData) const;
@@ -372,88 +415,76 @@ private:
QString signatureParameter(const AbstractMetaArgument &arg) const;
/// Writes the implementation of all methods part of python sequence protocol
void writeSequenceMethods(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &context) const;
static void writeTypeAsSequenceDefinition(TextStream &s,
- const AbstractMetaClass *metaClass);
+ const AbstractMetaClassCPtr &metaClass);
/// Writes the PyMappingMethods structure for types that supports the python mapping protocol.
static void writeTypeAsMappingDefinition(TextStream &s,
- const AbstractMetaClass *metaClass);
+ const AbstractMetaClassCPtr &metaClass);
void writeMappingMethods(TextStream &s,
- const AbstractMetaClass *metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const GeneratorContext &context) const;
- void writeTypeAsNumberDefinition(TextStream &s, const AbstractMetaClass *metaClass) const;
-
- static void writeTpTraverseFunction(TextStream &s, const AbstractMetaClass *metaClass);
- static void writeTpClearFunction(TextStream &s, const AbstractMetaClass *metaClass);
-
- void writeCopyFunction(TextStream &s, const GeneratorContext &context) const;
-
- QString cppFieldAccess(const AbstractMetaField &metaField,
- const GeneratorContext &context) const;
- void writeGetterFunction(TextStream &s,
- const AbstractMetaField &metaField,
- const GeneratorContext &context) const;
- void writeGetterFunction(TextStream &s,
- const QPropertySpec &property,
- const GeneratorContext &context) const;
- void writeSetterFunctionPreamble(TextStream &s,
- const QString &name,
- const QString &funcName,
- const AbstractMetaType &type,
- const GeneratorContext &context) const;
- void writeSetterFunction(TextStream &s,
- const AbstractMetaField &metaField,
- const GeneratorContext &context) const;
- void writeSetterFunction(TextStream &s,
- const QPropertySpec &property,
- const GeneratorContext &context) const;
-
- void writeRichCompareFunctionHeader(TextStream &s,
- const QString &baseName,
- const GeneratorContext &context) const;
- static void writeRichCompareFunctionFooter(TextStream &s,
- const QString &baseName);
+ void writeTypeAsNumberDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass) const;
+
+ static void writeTpTraverseFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass);
+ static void writeTpClearFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass);
+
+ static QString writeCopyFunction(TextStream &s, TextStream &definitionStream,
+ TextStream &signatureStream, const GeneratorContext &context);
+
+ static QString cppFieldAccess(const AbstractMetaField &metaField,
+ const GeneratorContext &context);
+ static void writeGetterFunction(TextStream &s,
+ const AbstractMetaField &metaField,
+ const GeneratorContext &context);
+ static void writeGetterFunction(TextStream &s,
+ const QPropertySpec &property,
+ const GeneratorContext &context);
+ static void writeSetterFunctionPreamble(TextStream &s,
+ const QString &name,
+ const QString &funcName,
+ const AbstractMetaType &type,
+ const GeneratorContext &context);
+ static void writeSetterFunction(TextStream &s,
+ const AbstractMetaField &metaField,
+ const GeneratorContext &context);
+ static void writeSetterFunction(TextStream &s,
+ const QPropertySpec &property,
+ const GeneratorContext &context);
+
+ static void writeRichCompareFunctionHeader(TextStream &s,
+ const QString &baseName,
+ const GeneratorContext &context);
void writeRichCompareFunction(TextStream &s, const GeneratorContext &context) const;
void writeSmartPointerRichCompareFunction(TextStream &s, const GeneratorContext &context) const;
- void writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums,
- ErrorReturn errorReturn) const;
- void writeEnumInitialization(TextStream &s, const AbstractMetaEnum &metaEnum,
- ErrorReturn errorReturn) const;
+ static void writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums);
+ static bool writeEnumInitialization(TextStream &s, const AbstractMetaEnum &metaEnum);
- static void writeSignalInitialization(TextStream &s, const AbstractMetaClass *metaClass);
-
- static void writeFlagsMethods(TextStream &s, const AbstractMetaEnum &cppEnum);
- static void writeFlagsToLong(TextStream &s, const AbstractMetaEnum &cppEnum);
- static void writeFlagsNonZero(TextStream &s, const AbstractMetaEnum &cppEnum);
- static void writeFlagsNumberMethodsDefinition(TextStream &s, const AbstractMetaEnum &cppEnum);
- static void writeFlagsNumberMethodsDefinitions(TextStream &s,
- const AbstractMetaEnumList &enums);
- static void writeFlagsBinaryOperator(TextStream &s,
- const AbstractMetaEnum &cppEnum,
- const QString &pyOpName,
- const QString &cppOpName);
- static void writeFlagsUnaryOperator(TextStream &s,
- const AbstractMetaEnum &cppEnum,
- const QString &pyOpName,
- const QString &cppOpName,
- bool boolResult = false);
-
- /// Writes the function that registers the multiple inheritance information for the classes that need it.
- static void writeMultipleInheritanceInitializerFunction(TextStream &s, const AbstractMetaClass *metaClass);
- /// Writes the implementation of special cast functions, used when we need to cast a class with multiple inheritance.
- static void writeSpecialCastFunction(TextStream &s, const AbstractMetaClass *metaClass);
+ static void writeSignalInitialization(TextStream &s, const AbstractMetaClassCPtr &metaClass);
+
+ /// Writes the function that registers the multiple inheritance information
+ /// for the classes that need it.
+ static void writeMultipleInheritanceInitializerFunction(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass);
+ /// Writes the implementation of special cast functions, used when we need
+ /// to cast a class with multiple inheritance.
+ static void writeSpecialCastFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass);
static void writePrimitiveConverterInitialization(TextStream &s,
- const CustomConversion *customConversion);
- static void writeEnumConverterInitialization(TextStream &s, const TypeEntry *enumType);
+ const CustomConversionPtr &customConversion);
static void writeEnumConverterInitialization(TextStream &s, const AbstractMetaEnum &metaEnum);
- QString writeContainerConverterInitialization(TextStream &s, const AbstractMetaType &type) const;
+ static QString writeContainerConverterInitialization(TextStream &s,
+ const AbstractMetaType &type,
+ const ApiExtractorResult &api);
void writeSmartPointerConverterInitialization(TextStream &s, const AbstractMetaType &ype) const;
- static void writeExtendedConverterInitialization(TextStream &s, const TypeEntry *externalType,
+
+ static QString typeInitStruct(const TypeEntryCPtr &te);
+ static void writeExtendedConverterInitialization(TextStream &s,
+ const TypeEntryCPtr &externalType,
const AbstractMetaClassCList &conversions);
void writeParentChildManagement(TextStream &s, const AbstractMetaFunctionCPtr &func,
@@ -472,24 +503,25 @@ private:
* \return name of the multiple inheritance information initializer function or
* an empty string if there is no multiple inheritance in its ancestry.
*/
- static QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass *metaClass);
+ static QString multipleInheritanceInitializerFunctionName(const AbstractMetaClassCPtr &metaClass);
/// Returns a list of all classes to which the given class could be cast.
- static QStringList getAncestorMultipleInheritance(const AbstractMetaClass *metaClass);
+ static QStringList getAncestorMultipleInheritance(const AbstractMetaClassCPtr &metaClass);
/// Returns true if the given class supports the python number protocol
- bool supportsNumberProtocol(const AbstractMetaClass *metaClass) const;
+ static bool supportsNumberProtocol(const AbstractMetaClassCPtr &metaClass);
/// Returns true if the given class supports the python sequence protocol
- static bool supportsSequenceProtocol(const AbstractMetaClass *metaClass) ;
+ static bool supportsSequenceProtocol(const AbstractMetaClassCPtr &metaClass) ;
/// Returns true if the given class supports the python mapping protocol
- static bool supportsMappingProtocol(const AbstractMetaClass *metaClass) ;
+ static bool supportsMappingProtocol(const AbstractMetaClassCPtr &metaClass) ;
/// Returns true if generator should produce getters and setters for the given class.
- bool shouldGenerateGetSetList(const AbstractMetaClass *metaClass) const;
+ static bool shouldGenerateGetSetList(const AbstractMetaClassCPtr &metaClass);
- void writeHashFunction(TextStream &s, const GeneratorContext &context) const;
+ static bool hasHashFunction(const AbstractMetaClassCPtr &c);
+ static void writeHashFunction(TextStream &s, const GeneratorContext &context);
/// Write default implementations for sequence protocol
void writeDefaultSequenceMethods(TextStream &s, const GeneratorContext &context) const;
@@ -497,23 +529,39 @@ private:
static void writeIndexError(TextStream &s, const QString &errorMsg,
ErrorReturn errorReturn);
- QString writeReprFunction(TextStream &s, const GeneratorContext &context,
- uint indirections) const;
-
- BoolCastFunctionOptional boolCast(const AbstractMetaClass *metaClass) const;
- bool hasBoolCast(const AbstractMetaClass *metaClass) const
+ static QString writeReprFunctionHeader(TextStream &s, const GeneratorContext &context);
+ static QString writeReprFunction(TextStream &s,
+ const GeneratorContext &context,
+ uint indirections);
+ static QString writeSmartPointerReprFunction(TextStream &s,
+ const GeneratorContext &context);
+ static QString writeSmartPointerDirFunction(TextStream &s,
+ TextStream &definitionStream,
+ TextStream &signatureStream,
+ const GeneratorContext &context);
+ static void writeReprFunctionFooter(TextStream &s);
+ static void writePyMethodDefs(TextStream &s, const QString &className,
+ const QString &methodsDefinitions);
+
+ void writeModuleCodeSnips(TextStream &s, const CodeSnipList &codeSnips,
+ TypeSystem::CodeSnipPosition position,
+ TypeSystem::Language language) const;
+
+ static bool hasBoolCast(const AbstractMetaClassCPtr &metaClass)
{ return boolCast(metaClass).has_value(); }
std::optional<AbstractMetaType>
- findSmartPointerInstantiation(const SmartPointerTypeEntry *pointer,
- const TypeEntry *pointee) const;
+ findSmartPointerInstantiation(const SmartPointerTypeEntryCPtr &pointer,
+ const TypeEntryCPtr &pointee) const;
void clearTpFuncs();
+ static QString chopType(QString s);
QHash<QString, QString> m_tpFuncs;
-
- static const char *PYTHON_TO_CPPCONVERSION_STRUCT;
+ QHash<QString, QString> m_nbFuncs;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(CppGenerator::CppSelfDefinitionFlags)
+TextStream &operator<<(TextStream &s, CppGenerator::ErrorReturn r);
+
#endif // CPPGENERATOR_H
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
index 91c56b284..00e0cabea 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
@@ -2,16 +2,20 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppgenerator.h"
+#include "generatorstrings.h"
#include <abstractmetalang.h>
#include "apiextractorresult.h"
#include "ctypenames.h"
#include "containertypeentry.h"
#include "textstream.h"
+#include "typedatabase.h"
#include <QtCore/QDebug>
#include <algorithm>
+using namespace Qt::StringLiterals;
+
// Write a PyMethodDef entry, allowing for registering C++ functions
// under different names for Python.
static void writeMethod(TextStream &s, const QString &privateObjType,
@@ -51,23 +55,37 @@ static void writeSlot(TextStream &s, const QString &privateObjType,
// Write creation function from C++ reference, used by field accessors
// and getters which are within extern "C"
+
+enum ContainerCreationFlag
+{
+ None = 0,
+ Const = 0x1,
+ Allocate = 0x2
+};
+
+Q_DECLARE_FLAGS(ContainerCreationFlags, ContainerCreationFlag)
+Q_DECLARE_OPERATORS_FOR_FLAGS(ContainerCreationFlags)
+
static void writeContainerCreationFunc(TextStream &s,
const QString &funcName,
const QString &typeFName,
const QString &containerSignature,
- bool isConst = false)
+ ContainerCreationFlags flags = {})
{
// creation function from C++ reference, used by field accessors
// which are within extern "C"
s << "extern \"C\" PyObject *" << funcName << '(';
- if (isConst)
+ if (flags.testFlag(ContainerCreationFlag::Const))
s << "const ";
s << containerSignature << "* ct)\n{\n" << indent
<< "auto *container = PyObject_New(ShibokenContainer, " << typeFName << "());\n"
<< "auto *d = new ShibokenSequenceContainerPrivate<"
<< containerSignature << ">();\n";
- if (isConst) {
+ if (flags.testFlag(ContainerCreationFlag::Allocate)) {
+ s << "d->m_list = new " << containerSignature << "(*ct);\n"
+ << "d->m_ownsList = true;\n";
+ } else if (flags.testFlag(ContainerCreationFlag::Const)) {
s << "d->m_list = const_cast<" << containerSignature << " *>(ct);\n"
<< "d->m_const = true;\n";
} else {
@@ -78,34 +96,22 @@ static void writeContainerCreationFunc(TextStream &s,
<< "}\n\n";
}
-// Generate code for a type wrapping a C++ container instantiation
-CppGenerator::OpaqueContainerData
- CppGenerator::writeOpaqueContainerConverterFunctions(TextStream &s,
- const AbstractMetaType &containerType) const
+// Generate template specialization of value converter helper
+void CppGenerator::writeOpaqueContainerValueConverter(TextStream &s,
+ const AbstractMetaType &valueType) const
{
- OpaqueContainerData result;
- const auto &valueType = containerType.instantiations().constFirst();
- const auto *containerTypeEntry = static_cast<const ContainerTypeEntry *>(containerType.typeEntry());
- result.name = containerTypeEntry->opaqueContainerName(valueType.typeEntry()->name());
-
- const auto cppSignature = containerType.cppSignature();
- s << "\n// Binding for " << cppSignature << "\n\n";
-
// Generate template specialization of value converter helper unless it is already there
- const QString pyArg = u"pyArg"_qs;
- const QString cppArg = u"cppArg"_qs;
-
const QString valueTypeName = valueType.cppSignature();
const QString checkFunction = cpythonCheckFunction(valueType);
s << "template <>\nstruct ShibokenContainerValueConverter<"
<< valueTypeName << ">\n{\n";
// Type check
- s << indent << "static bool checkValue(PyObject *" << pyArg << ")\n{\n"
+ s << indent << "static bool checkValue(PyObject *" << PYTHON_ARG << ")\n{\n"
<< indent << "return " << checkFunction;
if (!checkFunction.contains(u'('))
s << '(';
- s << pyArg << ");\n"
+ s << PYTHON_ARG << ");\n"
<< outdent << "}\n\n";
// C++ to Python
@@ -117,52 +123,79 @@ CppGenerator::OpaqueContainerData
s << valueTypeName << ' ';
if (passByConstRef)
s << '&';
- s << cppArg << ")\n{\n" << indent << "return ";
- writeToPythonConversion(s, valueType, nullptr, cppArg);
+ s << CPP_ARG << ")\n{\n" << indent << "return ";
+ writeToPythonConversion(s, valueType, nullptr, CPP_ARG);
s << ";\n" << outdent << "}\n\n";
// Python to C++
s << "static std::optional<" << valueTypeName << "> convertValueToCpp(PyObject *"
- << pyArg << ")\n{\n" << indent;
+ << PYTHON_ARG << ")\n{\n" << indent;
s << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << ";\n"
<< "if (!(";
- writeTypeCheck(s, valueType, pyArg), isNumber(valueType.typeEntry());
+ writeTypeCheck(s, valueType, PYTHON_ARG), isNumber(valueType.typeEntry());
s << ")) {\n" << indent
<< "Shiboken::Errors::setWrongContainerType();\n"
<< "return {};\n" << outdent << "}\n";
- writePythonToCppTypeConversion(s, valueType, pyArg, cppArg, nullptr, {});
- s << "return " << cppArg << ";\n" << outdent << "}\n" << outdent << "};\n\n";
+ writePythonToCppTypeConversion(s, valueType, PYTHON_ARG, CPP_ARG, nullptr, {});
+ s << "return " << CPP_ARG << ";\n" << outdent << "}\n" << outdent << "};\n\n";
+}
+
+// Generate code for a type wrapping a C++ container instantiation
+CppGenerator::OpaqueContainerData
+ CppGenerator::writeOpaqueContainerConverterFunctions(TextStream &s,
+ const AbstractMetaType &containerType,
+ QSet<AbstractMetaType> *valueTypes) const
+{
+ OpaqueContainerData result;
+ const auto &valueType = containerType.instantiations().constFirst();
+ const auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(containerType.typeEntry());
+ result.name =
+ containerTypeEntry->opaqueContainerName(containerType.instantiationCppSignatures());
+
+ const auto cppSignature = containerType.cppSignature();
+ s << "\n// Binding for " << cppSignature << "\n\n";
- const QString privateObjType = u"ShibokenSequenceContainerPrivate<"_qs
+ if (!valueTypes->contains(valueType)) {
+ valueTypes->insert(valueType);
+ writeOpaqueContainerValueConverter(s, valueType);
+ }
+
+ const QString privateObjType = u"ShibokenSequenceContainerPrivate<"_s
+ cppSignature + u'>';
// methods
- const bool isStdVector = containerType.name() == u"std::vector";
- const QString methods = result.name + u"_methods"_qs;
+ const QString &containerName = containerType.name();
+ const bool isStdVector = containerName == u"std::vector";
+ const auto kind = containerTypeEntry->containerKind();
+ const bool isFixed = kind == ContainerTypeEntry::SpanContainer || containerName == u"std::array";
+ const QString methods = result.name + u"_methods"_s;
s << "static PyMethodDef " << methods << "[] = {\n" << indent;
- writeMethod(s, privateObjType, "push_back");
- writeMethod(s, privateObjType, "push_back", "append"); // Qt convention
- writeNoArgsMethod(s, privateObjType, "clear");
- writeNoArgsMethod(s, privateObjType, "pop_back");
- writeNoArgsMethod(s, privateObjType, "pop_back", "removeLast"); // Qt convention
- if (!isStdVector) {
- writeMethod(s, privateObjType, "push_front");
- writeMethod(s, privateObjType, "push_front", "prepend"); // Qt convention
- writeNoArgsMethod(s, privateObjType, "pop_front");
- writeMethod(s, privateObjType, "pop_front", "removeFirst"); // Qt convention
+ if (!isFixed) {
+ writeMethod(s, privateObjType, "push_back");
+ writeMethod(s, privateObjType, "push_back", "append"); // Qt convention
+ writeNoArgsMethod(s, privateObjType, "clear");
+ writeNoArgsMethod(s, privateObjType, "pop_back");
+ writeNoArgsMethod(s, privateObjType, "pop_back", "removeLast"); // Qt convention
+ if (!isStdVector) {
+ writeMethod(s, privateObjType, "push_front");
+ writeMethod(s, privateObjType, "push_front", "prepend"); // Qt convention
+ writeNoArgsMethod(s, privateObjType, "pop_front");
+ writeMethod(s, privateObjType, "pop_front", "removeFirst"); // Qt convention
+ }
+ writeMethod(s, privateObjType, "reserve"); // SFINAE'd out for list
+ writeNoArgsMethod(s, privateObjType, "capacity");
}
- writeMethod(s, privateObjType, "reserve");
- writeNoArgsMethod(s, privateObjType, "capacity");
writeNoArgsMethod(s, privateObjType, "data");
writeNoArgsMethod(s, privateObjType, "constData");
s << "{nullptr, nullptr, 0, nullptr} // Sentinel\n"
<< outdent << "};\n\n";
// slots
- const QString slotsList = result.name + u"_slots"_qs;
+ const QString slotsList = result.name + u"_slots"_s;
s << "static PyType_Slot " << slotsList << "[] = {\n" << indent;
writeSlot(s, privateObjType, "Py_tp_init", "tpInit");
- writeSlot(s, privateObjType, "Py_tp_new", "tpNew");
+ const auto *tpNew = containerTypeEntry->viewOn() == nullptr ? "tpNew" : "tpNewInvalid";
+ writeSlot(s, privateObjType, "Py_tp_new", tpNew);
writeSlot(s, privateObjType, "Py_tp_free", "tpFree");
writeSlot(s, "Py_tp_dealloc", "Sbk_object_dealloc"); // FIXME?
writeSlot(s, "Py_tp_methods", methods.toUtf8().constData());
@@ -172,55 +205,62 @@ CppGenerator::OpaqueContainerData
s << "{0, nullptr}\n" << outdent << "};\n\n";
// spec
- const QString specName = result.name + u"_spec"_qs;
- const QString name = moduleName() + u'.' + result.name;
+ const QString specName = result.name + u"_spec"_s;
+ const QString name = TypeDatabase::instance()->defaultPackageName()
+ + u'.' + result.name;
s << "static PyType_Spec " << specName << " = {\n" << indent
<< "\"" << name.count(u'.') << ':' << name << "\",\n"
<< "sizeof(ShibokenContainer),\n0,\nPy_TPFLAGS_DEFAULT,\n"
<< slotsList << outdent << "\n};\n\n";
// type creation function that sets a key in the type dict.
- const QString typeCreationFName = u"create"_qs + result.name + u"Type"_qs;
+ const QString typeCreationFName = u"create"_s + result.name + u"Type"_s;
s << "static inline PyTypeObject *" << typeCreationFName << "()\n{\n" << indent
<< "auto *result = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&"
<< specName << "));\nPy_INCREF(Py_True);\n"
- << "PyDict_SetItem(result->tp_dict, "
+ << "Shiboken::AutoDecRef tpDict(PepType_GetDict(result));\n"
+ << "PyDict_SetItem(tpDict.object(), "
"Shiboken::PyMagicName::opaque_container(), Py_True);\n"
<< "return result;\n" << outdent << "}\n\n";
// _TypeF() function
- const QString typeFName = result.name + u"_TypeF"_qs;
+ const QString typeFName = result.name + u"_TypeF"_s;
s << "static PyTypeObject *" << typeFName << "()\n{\n" << indent
<< "static PyTypeObject *type = " << typeCreationFName
<< "();\nreturn type;\n" << outdent << "}\n\n";
// creation functions from C++ references
- writeContainerCreationFunc(s, u"create"_qs + result.name, typeFName,
- containerType.cppSignature());
- writeContainerCreationFunc(s, u"createConst"_qs + result.name, typeFName,
- containerType.cppSignature(), true);
+ ContainerCreationFlags flags;
+ if (kind == ContainerTypeEntry::SpanContainer)
+ flags.setFlag(ContainerCreationFlag::Allocate);
+
+ writeContainerCreationFunc(s, u"create"_s + result.name, typeFName,
+ containerType.cppSignature(), flags);
+ flags.setFlag(ContainerCreationFlag::Const);
+ writeContainerCreationFunc(s, u"createConst"_s + result.name, typeFName,
+ containerType.cppSignature(), flags);
// Check function
- result.checkFunctionName = result.name + u"_Check"_qs;
- s << "extern \"C\" int " << result.checkFunctionName << "(PyObject *" << pyArg
- << ")\n{\n" << indent << "return " << pyArg << " != nullptr && "
- << pyArg << " != Py_None && " << pyArg << "->ob_type == "
+ result.checkFunctionName = result.name + u"_Check"_s;
+ s << "extern \"C\" int " << result.checkFunctionName << "(PyObject *" << PYTHON_ARG
+ << ")\n{\n" << indent << "return " << PYTHON_ARG << " != nullptr && "
+ << PYTHON_ARG << " != Py_None && " << PYTHON_ARG << "->ob_type == "
<< typeFName << "();\n" << outdent << "}\n\n";
// SBK converter Python to C++
- result.pythonToConverterFunctionName = u"PythonToCpp"_qs + result.name;
+ result.pythonToConverterFunctionName = u"PythonToCpp"_s + result.name;
s << "extern \"C\" void " << result.pythonToConverterFunctionName
- << "(PyObject *" << pyArg << ", void *cppOut)\n{\n" << indent
+ << "(PyObject *" << PYTHON_ARG << ", void *cppOut)\n{\n" << indent
<< "auto *d = ShibokenSequenceContainerPrivate<" << cppSignature
- << ">::get(" << pyArg << ");\n"
+ << ">::get(" << PYTHON_ARG << ");\n"
<< "*reinterpret_cast<" << cppSignature << "**>(cppOut) = d->m_list;\n"
<< outdent << "}\n\n";
// SBK check function for converting Python to C++ that returns the converter
- result.converterCheckFunctionName = u"is"_qs + result.name + u"PythonToCppConvertible"_qs;
+ result.converterCheckFunctionName = u"is"_s + result.name + u"PythonToCppConvertible"_s;
s << "extern \"C\" PythonToCppFunc " << result.converterCheckFunctionName
- << "(PyObject *" << pyArg << ")\n{\n" << indent << "if ("
- << result.checkFunctionName << '(' << pyArg << "))\n" << indent
+ << "(PyObject *" << PYTHON_ARG << ")\n{\n" << indent << "if ("
+ << result.checkFunctionName << '(' << PYTHON_ARG << "))\n" << indent
<< "return " << result.pythonToConverterFunctionName << ";\n"
<< outdent << "return {};\n" << outdent << "}\n\n";
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
new file mode 100644
index 000000000..1b893640a
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_smartpointer.cpp
@@ -0,0 +1,486 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "cppgenerator.h"
+#include "generatorstrings.h"
+#include "generatorcontext.h"
+#include <apiextractorresult.h>
+#include <abstractmetafunction.h>
+#include <abstractmetalang.h>
+#include <codesnip.h>
+#include <exception.h>
+#include <messages.h>
+#include <textstream.h>
+#include <overloaddata.h>
+#include <smartpointertypeentry.h>
+
+#include <QtCore/QDebug>
+
+using namespace Qt::StringLiterals;
+
+static const char smartPtrComment[] =
+ "// Try to find the 'name' attribute, by retrieving the PyObject for "
+ "the corresponding C++ object held by the smart pointer.\n";
+
+static QString smartPointerGetter(const GeneratorContext &context)
+{
+ const auto te = context.metaClass()->typeEntry();
+ Q_ASSERT(te->isSmartPointer());
+ return std::static_pointer_cast<const SmartPointerTypeEntry>(te)->getter();
+}
+
+struct callGetter
+{
+ explicit callGetter(const GeneratorContext &context) : m_context(context) {}
+
+ const GeneratorContext &m_context;
+};
+
+TextStream &operator<<(TextStream &str, const callGetter &c)
+{
+ str << "PyObject_CallMethod(self, \"" << smartPointerGetter(c.m_context) << "\", 0)";
+ return str;
+}
+
+// Helpers to collect all smart pointer pointee base classes
+static AbstractMetaClassCList
+ findSmartPointeeBaseClasses(const ApiExtractorResult &api,
+ const AbstractMetaType &smartPointerType)
+{
+ AbstractMetaClassCList result;
+ auto instantiationsTe = smartPointerType.instantiations().at(0).typeEntry();
+ auto targetClass = AbstractMetaClass::findClass(api.classes(), instantiationsTe);
+ if (targetClass != nullptr)
+ result = targetClass->allTypeSystemAncestors();
+ return result;
+}
+
+using ComparisonOperatorList = QList<AbstractMetaFunction::ComparisonOperatorType>;
+
+// Return the available comparison operators for smart pointers
+static ComparisonOperatorList smartPointeeComparisons(const GeneratorContext &context)
+{
+ Q_ASSERT(context.forSmartPointer());
+ auto te = context.preciseType().instantiations().constFirst().typeEntry();
+ if (isExtendedCppPrimitive(te)) { // Primitive pointee types have all
+ return {AbstractMetaFunction::OperatorEqual,
+ AbstractMetaFunction::OperatorNotEqual,
+ AbstractMetaFunction::OperatorLess,
+ AbstractMetaFunction::OperatorLessEqual,
+ AbstractMetaFunction::OperatorGreater,
+ AbstractMetaFunction::OperatorGreaterEqual};
+ }
+
+ const auto pointeeClass = context.pointeeClass();
+ if (!pointeeClass)
+ return {};
+
+ ComparisonOperatorList result;
+ const auto &comparisons =
+ pointeeClass->operatorOverloads(OperatorQueryOption::SymmetricalComparisonOp);
+ for (const auto &f : comparisons) {
+ const auto ct = f->comparisonOperatorType().value();
+ if (!result.contains(ct))
+ result.append(ct);
+ }
+ return result;
+}
+
+std::optional<AbstractMetaType>
+ CppGenerator::findSmartPointerInstantiation(const SmartPointerTypeEntryCPtr &pointer,
+ const TypeEntryCPtr &pointee) const
+{
+ for (const auto &smp : api().instantiatedSmartPointers()) {
+ const auto &i = smp.type;
+ if (i.typeEntry() == pointer && i.instantiations().at(0).typeEntry() == pointee)
+ return i;
+ }
+ return {};
+}
+
+static bool hasParameterPredicate(const AbstractMetaFunctionCPtr &f)
+{
+ return !f->arguments().isEmpty();
+}
+
+void CppGenerator::generateSmartPointerClass(TextStream &s, const GeneratorContext &classContext)
+{
+ s.setLanguage(TextStream::Language::Cpp);
+ AbstractMetaClassCPtr metaClass = classContext.metaClass();
+ const auto typeEntry = std::static_pointer_cast<const SmartPointerTypeEntry>(metaClass->typeEntry());
+ const bool hasPointeeClass = classContext.pointeeClass() != nullptr;
+ const auto smartPointerType = typeEntry->smartPointerType();
+ const bool isValueHandle = smartPointerType ==TypeSystem::SmartPointerType::ValueHandle;
+
+ IncludeGroup includes{u"Extra includes"_s, typeEntry->extraIncludes()};
+ if (hasPointeeClass)
+ includes.append(classContext.pointeeClass()->typeEntry()->include());
+ includes.includes.append({Include::IncludePath, u"sbksmartpointer.h"_s});
+ generateIncludes(s, classContext, {includes});
+
+ s << '\n';
+
+ // class inject-code native/beginning
+ if (!typeEntry->codeSnips().isEmpty()) {
+ writeClassCodeSnips(s, typeEntry->codeSnips(),
+ TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode,
+ classContext);
+ s << '\n';
+ }
+
+ StringStream smd(TextStream::Language::Cpp);
+ StringStream md(TextStream::Language::Cpp);
+ StringStream signatureStream(TextStream::Language::Cpp);
+
+ s << openTargetExternC;
+
+ const auto &functionGroups = getFunctionGroups(metaClass);
+
+ // Skip all public methods of the smart pointer except for the special
+ // methods declared in the type entry.
+
+ auto ctors = metaClass->queryFunctions(FunctionQueryOption::Constructors);
+ if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
+ auto end = std::remove_if(ctors.begin(), ctors.end(), hasParameterPredicate);
+ ctors.erase(end, ctors.end());
+ }
+
+ if (!ctors.isEmpty()) {
+ OverloadData overloadData(ctors, api());
+ writeConstructorWrapper(s, overloadData, classContext);
+ writeSignatureInfo(signatureStream, overloadData);
+ }
+
+ if (!typeEntry->resetMethod().isEmpty()) {
+ auto it = functionGroups.constFind(typeEntry->resetMethod());
+ if (it == functionGroups.cend())
+ throw Exception(msgCannotFindSmartPointerMethod(typeEntry, typeEntry->resetMethod()));
+ AbstractMetaFunctionCList resets = it.value();
+ if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
+ auto end = std::remove_if(resets.begin(), resets.end(), hasParameterPredicate);
+ resets.erase(end, resets.end());
+ }
+ if (!resets.isEmpty())
+ writeMethodWrapper(s, md, signatureStream, resets, classContext);
+ }
+
+ auto it = functionGroups.constFind(typeEntry->getter());
+ if (it == functionGroups.cend() || it.value().size() != 1)
+ throw Exception(msgCannotFindSmartPointerGetter(typeEntry));
+
+ writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
+
+ QStringList optionalMethods;
+ if (!typeEntry->refCountMethodName().isEmpty())
+ optionalMethods.append(typeEntry->refCountMethodName());
+ const QString valueCheckMethod = typeEntry->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty() && !valueCheckMethod.startsWith(u"operator"))
+ optionalMethods.append(valueCheckMethod);
+ if (!typeEntry->nullCheckMethod().isEmpty())
+ optionalMethods.append(typeEntry->nullCheckMethod());
+
+ for (const QString &optionalMethod : optionalMethods) {
+ auto it = functionGroups.constFind(optionalMethod);
+ if (it == functionGroups.cend() || it.value().size() != 1)
+ throw Exception(msgCannotFindSmartPointerMethod(typeEntry, optionalMethod));
+ writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
+ }
+
+ writeCopyFunction(s, md, signatureStream, classContext);
+ writeSmartPointerDirFunction(s, md, signatureStream, classContext);
+
+ const QString methodsDefinitions = md.toString();
+ const QString singleMethodDefinitions = smd.toString();
+
+ const QString className = chopType(cpythonTypeName(typeEntry));
+
+ // Write single method definitions
+ s << singleMethodDefinitions;
+
+ // Write methods definition
+ writePyMethodDefs(s, className, methodsDefinitions);
+
+ // Write tp_s/getattro function
+ const auto boolCastOpt = boolCast(metaClass);
+ writeSmartPointerGetattroFunction(s, classContext, boolCastOpt);
+ writeSmartPointerSetattroFunction(s, classContext);
+
+ if (boolCastOpt.has_value())
+ writeNbBoolFunction(classContext, boolCastOpt.value(), s);
+
+ if (smartPointerType == TypeSystem::SmartPointerType::Shared)
+ writeSmartPointerRichCompareFunction(s, classContext);
+
+ s << closeExternC;
+
+ if (hasHashFunction(metaClass))
+ writeHashFunction(s, classContext);
+
+ // Write tp_traverse and tp_clear functions.
+ writeTpTraverseFunction(s, metaClass);
+ writeTpClearFunction(s, metaClass);
+
+ writeClassDefinition(s, metaClass, classContext);
+
+ s << '\n';
+
+ writeConverterFunctions(s, metaClass, classContext);
+ writeClassRegister(s, metaClass, classContext, signatureStream);
+
+ // class inject-code native/end
+ if (!typeEntry->codeSnips().isEmpty()) {
+ writeClassCodeSnips(s, typeEntry->codeSnips(),
+ TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode,
+ classContext);
+ s << '\n';
+ }
+}
+
+void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
+ const AbstractMetaType &smartPointerType) const
+{
+ const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
+ if (baseClasses.isEmpty())
+ return;
+
+ auto smartPointerTypeEntry =
+ std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
+
+ // TODO: Missing conversion to smart pointer pointer type:
+
+ s << "// Register smartpointer conversion for all derived classes\n";
+ for (const auto &base : baseClasses) {
+ auto baseTe = base->typeEntry();
+ if (smartPointerTypeEntry->matchesInstantiation(baseTe)) {
+ if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
+ const auto smartTargetType = opt.value();
+ s << "// SmartPointer derived class: "
+ << smartTargetType.cppSignature() << "\n";
+ writePythonToCppConversionFunctions(s, smartPointerType,
+ smartTargetType, {}, {}, {});
+ }
+ }
+ }
+}
+
+void CppGenerator::writeSmartPointerCppSelfConversion(TextStream &s,
+ const GeneratorContext &context)
+{
+ Q_ASSERT(context.forSmartPointer());
+ s << cpythonWrapperCPtr(context.preciseType(), u"self"_s);
+}
+
+void CppGenerator::writeSmartPointerCppSelfDefinition(TextStream &s,
+ const GeneratorContext &context,
+ ErrorReturn errorReturn,
+ CppSelfDefinitionFlags flags)
+{
+ Q_ASSERT(context.forSmartPointer());
+ writeInvalidPyObjectCheck(s, u"self"_s, errorReturn);
+ writeCppSelfVarDef(s, flags);
+ writeSmartPointerCppSelfConversion(s, context);
+ s << ";\n";
+}
+
+void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s,
+ const AbstractMetaType &type) const
+{
+ const QByteArray cppSignature = type.cppSignature().toUtf8();
+ auto writeConversionRegister = [&s](const AbstractMetaType &sourceType,
+ const QString &targetTypeName,
+ const QString &targetConverter)
+ {
+ const QString sourceTypeName = fixedCppTypeName(sourceType);
+ const QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
+ const QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
+
+ writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
+ };
+
+ const auto classes = findSmartPointeeBaseClasses(api(), type);
+ if (classes.isEmpty())
+ return;
+
+ auto smartPointerTypeEntry = std::static_pointer_cast<const SmartPointerTypeEntry>(type.typeEntry());
+
+ s << "// Register SmartPointer converter for type '" << cppSignature << "'." << '\n'
+ << "///////////////////////////////////////////////////////////////////////////////////////\n\n";
+
+ for (const auto &base : classes) {
+ auto baseTe = base->typeEntry();
+ if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
+ const auto smartTargetType = opt.value();
+ s << "// Convert to SmartPointer derived class: ["
+ << smartTargetType.cppSignature() << "]\n";
+ const QString converter = u"Shiboken::Conversions::getConverter(\""_s
+ + smartTargetType.cppSignature() + u"\")"_s;
+ writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter);
+ } else {
+ s << "// Class not found:" << type.instantiations().at(0).cppSignature();
+ }
+ }
+
+ s << "///////////////////////////////////////////////////////////////////////////////////////" << '\n' << '\n';
+}
+
+void CppGenerator::writeSmartPointerRichCompareFunction(TextStream &s,
+ const GeneratorContext &context) const
+{
+ static const char selfPointeeVar[] = "cppSelfPointee";
+ static const char cppArg0PointeeVar[] = "cppArg0Pointee";
+
+ const auto metaClass = context.metaClass();
+ QString baseName = cpythonBaseName(metaClass);
+ writeRichCompareFunctionHeader(s, baseName, context);
+
+ s << "if (";
+ writeTypeCheck(s, context.preciseType(), PYTHON_ARG);
+ s << ") {\n" << indent;
+ writeArgumentConversion(s, context.preciseType(), CPP_ARG0,
+ PYTHON_ARG, ErrorReturn::Default, metaClass);
+
+ const auto te = context.preciseType().typeEntry();
+ Q_ASSERT(te->isSmartPointer());
+ const auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(te);
+
+ s << "const auto *" << selfPointeeVar << " = " << CPP_SELF_VAR
+ << '.' << ste->getter() << "();\n";
+ s << "const auto *" << cppArg0PointeeVar << " = " << CPP_ARG0
+ << '.' << ste->getter() << "();\n";
+
+ // If we have an object without any comparisons, only generate a simple
+ // equality check by pointee address
+ auto availableOps = smartPointeeComparisons(context);
+ const bool comparePointeeAddressOnly = availableOps.isEmpty();
+ if (comparePointeeAddressOnly) {
+ availableOps << AbstractMetaFunction::OperatorEqual
+ << AbstractMetaFunction::OperatorNotEqual;
+ } else {
+ // For value types with operators, we complain about nullptr
+ s << "if (" << selfPointeeVar << " == nullptr || " << cppArg0PointeeVar
+ << " == nullptr) {\n" << indent
+ << "PyErr_SetString(PyExc_NotImplementedError, \"nullptr passed to comparison.\");\n"
+ << ErrorReturn::Default << '\n' << outdent << "}\n";
+ }
+
+ s << "bool " << CPP_RETURN_VAR << "= false;\n"
+ << "switch (op) {\n";
+ for (auto op : availableOps) {
+ s << "case " << AbstractMetaFunction::pythonRichCompareOpCode(op) << ":\n"
+ << indent << CPP_RETURN_VAR << " = ";
+ if (comparePointeeAddressOnly) {
+ s << selfPointeeVar << ' ' << AbstractMetaFunction::cppComparisonOperator(op)
+ << ' ' << cppArg0PointeeVar << ";\n";
+ } else {
+ // Shortcut for equality: Check pointee address
+ if (op == AbstractMetaFunction::OperatorEqual
+ || op == AbstractMetaFunction::OperatorLessEqual
+ || op == AbstractMetaFunction::OperatorGreaterEqual) {
+ s << selfPointeeVar << " == " << cppArg0PointeeVar << " || ";
+ }
+ // Generate object's comparison
+ s << "*" << selfPointeeVar << ' '
+ << AbstractMetaFunction::cppComparisonOperator(op) << " *"
+ << cppArg0PointeeVar << ";\n";
+ }
+ s << "break;\n" << outdent;
+
+ }
+ if (availableOps.size() < 6) {
+ s << "default:\n" << indent
+ << richCompareComment
+ << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n" << outdent;
+ }
+ s << "}\n" << PYTHON_RETURN_VAR << " = " << CPP_RETURN_VAR
+ << " ? Py_True : Py_False;\n"
+ << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n"
+ << outdent << "}\n"
+ << "return Shiboken::returnFromRichCompare(" << PYTHON_RETURN_VAR << ");\n"
+ << outdent << "}\n\n";
+}
+
+void CppGenerator::writeSmartPointerSetattroFunction(TextStream &s,
+ const GeneratorContext &context)
+{
+ Q_ASSERT(context.forSmartPointer());
+ writeSetattroDefinition(s, context.metaClass());
+ s << smartPtrComment
+ << "if (auto *rawObj = " << callGetter(context) << ") {\n" << indent
+ << "if (PyObject_HasAttr(rawObj, name) != 0)\n" << indent
+ << "return PyObject_GenericSetAttr(rawObj, name, value);\n" << outdent
+ << "Py_DECREF(rawObj);\n" << outdent
+ << "}\n";
+ writeSetattroDefaultReturn(s);
+}
+
+void CppGenerator::writeSmartPointerGetattroFunction(TextStream &s,
+ const GeneratorContext &context,
+ const BoolCastFunctionOptional &boolCast)
+{
+ Q_ASSERT(context.forSmartPointer());
+ const auto metaClass = context.metaClass();
+ writeGetattroDefinition(s, metaClass);
+ s << "PyObject *tmp = PyObject_GenericGetAttr(self, name);\n"
+ << "if (tmp)\n" << indent << "return tmp;\n" << outdent
+ << "if (PyErr_ExceptionMatches(PyExc_AttributeError) == 0)\n"
+ << indent << "return nullptr;\n" << outdent
+ << "PyErr_Clear();\n";
+
+ if (boolCast.has_value()) {
+ writeSmartPointerCppSelfDefinition(s, context);
+ s << "if (";
+ writeNbBoolExpression(s, boolCast.value(), true /* invert */);
+ s << ") {\n" << indent
+ << R"(PyTypeObject *tp = Py_TYPE(self);
+PyErr_Format(PyExc_AttributeError, "Attempt to retrieve '%s' from null object '%s'.",
+ Shiboken::String::toCString(name), tp->tp_name);
+return nullptr;
+)" << outdent << "}\n";
+ }
+
+ // This generates the code which dispatches access to member functions
+ // and fields from the smart pointer to its pointee.
+ s << smartPtrComment
+ << "if (auto *rawObj = " << callGetter(context) << ") {\n" << indent
+ << "if (auto *attribute = PyObject_GetAttr(rawObj, name))\n"
+ << indent << "tmp = attribute;\n" << outdent
+ << "Py_DECREF(rawObj);\n" << outdent
+ << "}\n"
+ << "if (!tmp) {\n" << indent
+ << R"(PyTypeObject *tp = Py_TYPE(self);
+PyErr_Format(PyExc_AttributeError,
+ "'%.50s' object has no attribute '%.400s'",
+ tp->tp_name, Shiboken::String::toCString(name));
+)" << outdent
+ << "}\n"
+ << "return tmp;\n" << outdent << "}\n\n";
+}
+
+QString CppGenerator::writeSmartPointerReprFunction(TextStream &s,
+ const GeneratorContext &context)
+{
+ const auto metaClass = context.metaClass();
+ QString funcName = writeReprFunctionHeader(s, context);
+ s << "Shiboken::AutoDecRef pointee(" << callGetter(context) << ");\n"
+ << "return Shiboken::SmartPointer::repr(self, pointee);\n";
+ writeReprFunctionFooter(s);
+ return funcName;
+}
+
+QString CppGenerator::writeSmartPointerDirFunction(TextStream &s, TextStream &definitionStream,
+ TextStream &signatureStream,
+ const GeneratorContext &context)
+{
+ QString funcName = cpythonBaseName(context.metaClass()) + u"__dir__"_s;
+
+ signatureStream << fullPythonClassName(context.metaClass()) << ".__dir__()\n";
+ definitionStream << PyMethodDefEntry{u"__dir__"_s, funcName, {"METH_NOARGS"_ba}, {}}
+ << ",\n";
+
+ s << "extern \"C\"\n{\n"
+ << "static PyObject *" << funcName << "(PyObject *self)\n{\n" << indent
+ << "Shiboken::AutoDecRef pointee(" << callGetter(context) << ");\n"
+ << "return Shiboken::SmartPointer::dir(self, pointee);\n"
+ << outdent << "}\n} // extern C\n\n";
+ return funcName;
+}
diff --git a/sources/shiboken6/generator/shiboken/ctypenames.h b/sources/shiboken6/generator/shiboken/ctypenames.h
index 0444c99f2..f665b30ff 100644
--- a/sources/shiboken6/generator/shiboken/ctypenames.h
+++ b/sources/shiboken6/generator/shiboken/ctypenames.h
@@ -6,26 +6,26 @@
#include <QtCore/QString>
-static inline QString boolT() { return QStringLiteral("bool"); }
-static inline QString intT() { return QStringLiteral("int"); }
-static inline QString unsignedT() { return QStringLiteral("unsigned"); }
-static inline QString unsignedIntT() { return QStringLiteral("unsigned int"); }
-static inline QString longT() { return QStringLiteral("long"); }
-static inline QString unsignedLongT() { return QStringLiteral("unsigned long"); }
-static inline QString shortT() { return QStringLiteral("short"); }
-static inline QString unsignedShortT() { return QStringLiteral("unsigned short"); }
-static inline QString unsignedCharT() { return QStringLiteral("unsigned char"); }
-static inline QString longLongT() { return QStringLiteral("long long"); }
-static inline QString unsignedLongLongT() { return QStringLiteral("unsigned long long"); }
-static inline QString charT() { return QStringLiteral("char"); }
-static inline QString floatT() { return QStringLiteral("float"); }
-static inline QString doubleT() { return QStringLiteral("double"); }
-static inline QString constCharPtrT() { return QStringLiteral("const char*"); }
+constexpr auto boolT = QLatin1StringView("bool");
+constexpr auto intT = QLatin1StringView("int");
+constexpr auto unsignedT = QLatin1StringView("unsigned");
+constexpr auto unsignedIntT = QLatin1StringView("unsigned int");
+constexpr auto longT = QLatin1StringView("long");
+constexpr auto unsignedLongT = QLatin1StringView("unsigned long");
+constexpr auto shortT = QLatin1StringView("short");
+constexpr auto unsignedShortT = QLatin1StringView("unsigned short");
+constexpr auto unsignedCharT = QLatin1StringView("unsigned char");
+constexpr auto longLongT = QLatin1StringView("long long");
+constexpr auto unsignedLongLongT = QLatin1StringView("unsigned long long");
+constexpr auto charT = QLatin1StringView("char");
+constexpr auto floatT = QLatin1StringView("float");
+constexpr auto doubleT = QLatin1StringView("double");
+constexpr auto constCharPtrT = QLatin1StringView("const char*");
-static inline QString qByteArrayT() { return QStringLiteral("QByteArray"); }
-static inline QString qMetaObjectT() { return QStringLiteral("QMetaObject"); }
-static inline QString qObjectT() { return QStringLiteral("QObject"); }
-static inline QString qStringT() { return QStringLiteral("QString"); }
-static inline QString qVariantT() { return QStringLiteral("QVariant"); }
+constexpr auto qByteArrayT = QLatin1StringView("QByteArray");
+constexpr auto qMetaObjectT = QLatin1StringView("QMetaObject");
+constexpr auto qObjectT = QLatin1StringView("QObject");
+constexpr auto qStringT = QLatin1StringView("QString");
+constexpr auto qVariantT = QLatin1StringView("QVariant");
#endif // CTYPENAMES_H
diff --git a/sources/shiboken6/generator/shiboken/generatorargument.cpp b/sources/shiboken6/generator/shiboken/generatorargument.cpp
new file mode 100644
index 000000000..e81ad0797
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/generatorargument.cpp
@@ -0,0 +1,110 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "generatorargument.h"
+#include <abstractmetatype.h>
+#include <messages.h>
+#include <typesystem.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QSet>
+
+static bool isCppPrimitiveString(const AbstractMetaType &type)
+{
+ return type.referenceType() == NoReference && type.indirections() == 1
+ && AbstractMetaType::cppSignedCharTypes().contains(type.name());
+}
+
+GeneratorArgument GeneratorArgument::fromMetaType(const AbstractMetaType &type)
+{
+ GeneratorArgument result;
+
+ const auto typeEntry = type.typeEntry();
+ if (typeEntry->isCustom() || typeEntry->isVarargs())
+ return result;
+
+ result.indirections = -type.indirectionsV().size();
+ if (isCppPrimitiveString(type)
+ || type.isVoidPointer()
+ || type.typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern) {
+ result.indirections += 1;
+ }
+
+ if (typeEntry->isEnum()) {
+ result.type = Type::Enum;
+ } else if (typeEntry->isFlags()) {
+ result.type = Type::Flags;
+ } else if (typeEntry->isContainer()) {
+ result.type = Type::Container;
+ } else {
+ if (typeEntry->isPrimitive())
+ result.type = Type::Primitive;
+
+ const AbstractMetaTypeList &nestedArrayTypes = type.nestedArrayTypes();
+ if (!nestedArrayTypes.isEmpty()) {
+ if (nestedArrayTypes.constLast().isCppPrimitive()) {
+ result.type = Type::CppPrimitiveArray;
+ } else {
+ static QSet<QString> warnedTypes;
+ const QString &signature = type.cppSignature();
+ if (!warnedTypes.contains(signature)) {
+ warnedTypes.insert(signature);
+ qWarning("%s", qPrintable(msgUnknownArrayPointerConversion(signature)));
+ }
+ result.indirections -= 1;
+ }
+ }
+ }
+
+ if (result.type == Type::Other || result.type == Type::Primitive) {
+ if (type.valueTypeWithCopyConstructorOnlyPassed()) {
+ result.flags.setFlag(Flag::TreatAsPointer);
+ } else if ((type.isObjectType() || type.isPointer())
+ && !type.isUserPrimitive() && !type.isExtendedCppPrimitive()) {
+ result.flags.setFlag(Flag::PointerOrObjectType);
+ } else if (type.referenceType() == LValueReference
+ && !type.isUserPrimitive()
+ && !type.isExtendedCppPrimitive()) {
+ result.flags.setFlag(Flag::MayHaveImplicitConversion);
+ }
+ }
+
+ // For implicit conversions or containers, either value or pointer conversion
+ // may occur. An implicit conversion uses value conversion whereas the object
+ // itself uses pointer conversion. For containers, the PyList/container
+ // conversion is by value whereas opaque containers use pointer conversion.
+ // For a container passed by pointer, a local variable is also needed.
+ if (result.flags.testFlag(Flag::MayHaveImplicitConversion)
+ || type.generateOpaqueContainer()
+ || (result.type == Type::Container && result.indirections != 0)) {
+ result.flags.setFlag(Flag::ValueOrPointer);
+ }
+
+ if (result.type == Type::CppPrimitiveArray) {
+ result.conversion = Conversion::CppPrimitiveArray;
+ } else if (result.flags.testFlag(Flag::ValueOrPointer)) {
+ result.conversion = Conversion::ValueOrPointer;
+ ++result.indirections;
+ } else if (result.flags.testAnyFlags(Flag::TreatAsPointer | Flag::PointerOrObjectType)) {
+ result.conversion = Conversion::Pointer;
+ ++result.indirections;
+ }
+
+ return result;
+}
+
+QDebug operator<<(QDebug debug, const GeneratorArgument &a)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote();
+ debug.nospace();
+ debug << "GeneratorArgument(" << a.type;
+ if (a.conversion != GeneratorArgument::Conversion::Default)
+ debug << ", conversion=" << a.conversion;
+ if (a.flags)
+ debug << ", flags(" << a.flags;
+ if (a.indirections != 0)
+ debug << ", indirections=" << a.indirections;
+ debug << ')';
+ return debug;
+}
diff --git a/sources/shiboken6/generator/shiboken/generatorargument.h b/sources/shiboken6/generator/shiboken/generatorargument.h
new file mode 100644
index 000000000..385ad0f63
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/generatorargument.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef GENERATORARGUMENT_H
+#define GENERATORARGUMENT_H
+
+#include <QtCore/QFlags>
+#include <QtCore/qobjectdefs.h>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+class AbstractMetaType;
+
+/// A struct containing information on how the generator processes a function argument.
+struct GeneratorArgument
+{
+ Q_GADGET
+
+public:
+ enum class Type {
+ Other,
+ Primitive,
+ Enum,
+ Flags,
+ Container,
+ CppPrimitiveArray
+ };
+ Q_ENUM(Type)
+
+ enum class Conversion {
+ Default,
+ CppPrimitiveArray, // Similar to Default except default values
+ Pointer,
+ ValueOrPointer
+ };
+ Q_ENUM(Conversion)
+
+ enum class Flag {
+ TreatAsPointer = 0x1,
+ PointerOrObjectType = 0x2,
+ MayHaveImplicitConversion = 0x4,
+ ValueOrPointer = 0x8,
+ };
+ Q_ENUM(Flag)
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ static GeneratorArgument fromMetaType(const AbstractMetaType &type);
+
+ Flags flags;
+ /// Indirections from generated "cppArg<n>" variable to function argument.
+ qsizetype indirections = 0;
+ Type type = Type::Other;
+ Conversion conversion = Conversion::Default;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(GeneratorArgument::Flags)
+
+QDebug operator<<(QDebug debug, const GeneratorArgument &a);
+
+#endif // GENERATORARGUMENT_H
diff --git a/sources/shiboken6/generator/shiboken/generatorstrings.h b/sources/shiboken6/generator/shiboken/generatorstrings.h
new file mode 100644
index 000000000..9ce91e599
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/generatorstrings.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef GENERATORSTRINGS_H
+#define GENERATORSTRINGS_H
+
+#include <QtCore/QString>
+
+QString CPP_ARG_N(int i);
+QString CPP_ARG_REMOVED(int i);
+
+constexpr auto CPP_RETURN_VAR = QLatin1StringView("cppResult");
+constexpr auto CPP_SELF_VAR = QLatin1StringView("cppSelf");
+constexpr auto CPP_ARG = QLatin1StringView("cppArg");
+constexpr auto NULL_PTR = QLatin1StringView("nullptr");
+constexpr auto PYTHON_ARG = QLatin1StringView("pyArg");
+constexpr auto PYTHON_ARGS = QLatin1StringView("pyArgs");
+constexpr auto PYTHON_OVERRIDE_VAR = QLatin1StringView("pyOverride");
+constexpr auto PYTHON_RETURN_VAR = QLatin1StringView("pyResult");
+constexpr auto PYTHON_SELF_VAR = QLatin1StringView("self");
+constexpr auto PYTHON_TO_CPP_VAR = QLatin1StringView("pythonToCpp");
+
+constexpr auto CONV_RULE_OUT_VAR_SUFFIX = QLatin1StringView("_out");
+constexpr auto BEGIN_ALLOW_THREADS
+ = QLatin1StringView("PyThreadState *_save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS");
+constexpr auto END_ALLOW_THREADS
+ = QLatin1StringView("PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS");
+
+constexpr auto REPR_FUNCTION = QLatin1StringView("__repr__");
+
+constexpr auto CPP_ARG0 = QLatin1StringView("cppArg0");
+
+extern const char *const METHOD_DEF_SENTINEL;
+extern const char *const PYTHON_TO_CPPCONVERSION_STRUCT;
+extern const char *const openTargetExternC;
+extern const char *const closeExternC;
+extern const char *const richCompareComment;
+
+#endif // GENERATORSTRINGS_H
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
index 21d5c8f6e..1f574b47c 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -2,14 +2,18 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "headergenerator.h"
+#include "configurablescope.h"
+#include "generatorcontext.h"
#include <apiextractorresult.h>
+#include <abstractmetaargument.h>
#include <abstractmetaenum.h>
#include <abstractmetafield.h>
#include <abstractmetafunction.h>
#include <abstractmetalang.h>
#include <abstractmetalang_helpers.h>
#include <codesnip.h>
-#include <modifications.h>
+#include <clangparser/compilersupport.h>
+#include <exception.h>
#include <typedatabase.h>
#include <reporthandler.h>
#include <textstream.h>
@@ -17,16 +21,16 @@
#include "containertypeentry.h"
#include "enumtypeentry.h"
#include "flagstypeentry.h"
+#include <messages.h>
#include "namespacetypeentry.h"
#include "primitivetypeentry.h"
#include "typedefentry.h"
#include "typesystemtypeentry.h"
-#include "parser/codemodel.h"
-
#include "qtcompat.h"
#include <algorithm>
+#include <set>
#include <QtCore/QDir>
#include <QtCore/QTextStream>
@@ -35,23 +39,68 @@
using namespace Qt::StringLiterals;
-QString HeaderGenerator::headerFileNameForContext(const GeneratorContext &context)
+struct IndexValue
+{
+ QString name; // "SBK_..."
+ int value;
+ QString comment;
+};
+
+TextStream &operator<<(TextStream &s, const IndexValue &iv)
{
- return fileNameForContextHelper(context, u"_wrapper.h"_s);
+ s << " " << AlignedField(iv.name, 56) << " = " << iv.value << ',';
+ if (!iv.comment.isEmpty())
+ s << " // " << iv.comment;
+ s << '\n';
+ return s;
}
+// PYSIDE-504: Handling the "protected hack"
+// The problem: Creating wrappers when the class has private destructors.
+// You can see an example on Windows in qclipboard_wrapper.h and others.
+// Simply search for the text "// C++11: need to declare (unimplemented) destructor".
+// The protected hack is the definition "#define protected public".
+// For most compilers, this "hack" is enabled, because the problem of private
+// destructors simply vanishes.
+//
+// If one does not want to use this hack, then a new problem arises:
+// C++11 requires that a destructor is declared in a wrapper class when it is
+// private in the base class. There is no implementation allowed!
+//
+// Unfortunately, MSVC in recent versions supports C++11, and due to restrictive
+// rules, it is impossible to use the hack with this compiler.
+// More unfortunate: Clang, when C++11 is enabled, also enforces a declaration
+// of a private destructor, but it falsely then creates a linker error!
+//
+// Originally, we wanted to remove the protected hack. But due to the Clang
+// problem, we gave up on removal of the protected hack and use it always
+// when we can. This might change again when the Clang problem is solved.
+
+static bool alwaysGenerateDestructorDeclaration()
+{
+ return clang::compiler() == Compiler::Msvc;
+}
+
+const char *HeaderGenerator::protectedHackDefine = R"(// Workaround to access protected functions
+#ifndef protected
+# define protected public
+#endif
+
+)";
+
QString HeaderGenerator::fileNameForContext(const GeneratorContext &context) const
{
return headerFileNameForContext(context);
}
-void HeaderGenerator::writeCopyCtor(TextStream &s, const AbstractMetaClass *metaClass) const
+void HeaderGenerator::writeCopyCtor(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass)
{
s << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName()
<< "& self) : " << metaClass->qualifiedCppName() << "(self)\n{\n}\n\n";
}
-static void writeProtectedEnums(TextStream &s, const AbstractMetaClass *metaClass)
+static void writeProtectedEnums(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
const QString name = metaClass->qualifiedCppName();
for (const auto &e : metaClass->enums()) {
@@ -60,132 +109,181 @@ static void writeProtectedEnums(TextStream &s, const AbstractMetaClass *metaClas
}
}
-void HeaderGenerator::generateClass(TextStream &s, const GeneratorContext &classContextIn)
+void HeaderGenerator::generateClass(TextStream &s, const GeneratorContext &classContext)
{
- GeneratorContext classContext = classContextIn;
- const AbstractMetaClass *metaClass = classContext.metaClass();
- m_inheritedOverloads.clear();
+ const AbstractMetaClassCPtr metaClass = classContext.metaClass();
// write license comment
s << licenseComment();
QString wrapperName = classContext.effectiveClassName();
- QString outerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper();
- QString innerHeaderGuard;
+ QString outerHeaderGuard = getFilteredCppSignatureString(wrapperName);
// Header
s << "#ifndef SBK_" << outerHeaderGuard << "_H\n";
s << "#define SBK_" << outerHeaderGuard << "_H\n\n";
if (!avoidProtectedHack())
- s << "#define protected public\n\n";
+ s << protectedHackDefine;
- //Includes
- auto typeEntry = metaClass->typeEntry();
- s << typeEntry->include() << '\n';
- if (classContext.useWrapper() && !typeEntry->extraIncludes().isEmpty()) {
- s << "\n// Extra includes\n";
- for (const Include &inc : typeEntry->extraIncludes())
- s << inc.toString() << '\n';
+ // Includes
+ s << metaClass->typeEntry()->include() << '\n';
+ for (auto &inst : metaClass->templateBaseClassInstantiations())
+ s << inst.typeEntry()->include();
+
+ if (classContext.useWrapper())
+ writeWrapperClass(s, wrapperName, classContext);
+
+ s << "#endif // SBK_" << outerHeaderGuard << "_H\n\n";
+}
+
+void HeaderGenerator::writeWrapperClass(TextStream &s,
+ const QString &wrapperName,
+ const GeneratorContext &classContext) const
+{
+ const auto metaClass = classContext.metaClass();
+
+ if (avoidProtectedHack()) {
+ const auto includeGroups = classIncludes(metaClass);
+ for( const auto &includeGroup : includeGroups)
+ s << includeGroup;
}
- if (classContext.useWrapper() && usePySideExtensions() && metaClass->isQObject())
+ if (usePySideExtensions() && isQObject(metaClass))
s << "namespace PySide { class DynamicQMetaObject; }\n\n";
- while (classContext.useWrapper()) {
- if (!innerHeaderGuard.isEmpty()) {
- s << "# ifndef SBK_" << innerHeaderGuard << "_H\n";
- s << "# define SBK_" << innerHeaderGuard << "_H\n\n";
- s << "// Inherited base class:\n";
+ writeWrapperClassDeclaration(s, wrapperName, classContext);
+
+ // PYSIDE-500: Use also includes for inherited wrapper classes other
+ // modules, because without the protected hack, we sometimes need to
+ // cast inherited wrappers. CppGenerator generates include statements for
+ // the classes of the current module. For other modules, we insert the
+ // declarations as recursive headers, since wrapper headers are not
+ // installed. This keeps the file structure as simple as before the
+ // enhanced inheritance.
+ if (avoidProtectedHack()) {
+ const auto &baseClasses = allBaseClasses(classContext.metaClass());
+ for (const auto &baseClass : baseClasses) {
+ const auto gen = baseClass->typeEntry()->codeGeneration();
+ if (gen == TypeEntry::GenerateForSubclass) { // other module
+ const auto baseContext = contextForClass(baseClass);
+ if (baseContext.useWrapper())
+ writeInheritedWrapperClassDeclaration(s, baseContext);
+ }
}
+ }
+}
- // Class
- s << "class " << wrapperName
- << " : public " << metaClass->qualifiedCppName()
- << "\n{\npublic:\n" << indent;
-
- // Make protected enums accessible
- if (avoidProtectedHack()) {
- recurseClassHierarchy(metaClass, [&s] (const AbstractMetaClass *metaClass) {
- writeProtectedEnums(s, metaClass);
- return false;
- });
- }
+void HeaderGenerator::writeInheritedWrapperClassDeclaration(TextStream &s,
+ const GeneratorContext &classContext) const
+{
+ const QString wrapperName = classContext.effectiveClassName();
+ const QString innerHeaderGuard =
+ getFilteredCppSignatureString(wrapperName).toUpper();
- if (avoidProtectedHack() && metaClass->hasProtectedFields()) {
- s << "\n// Make protected fields accessible\n";
- const QString name = metaClass->qualifiedCppName();
- for (const auto &f : metaClass->fields()) {
- if (f.isProtected())
- s << "using " << name << "::" << f.originalName() << ";\n";
- }
- s << '\n';
- }
+ s << "# ifndef SBK_" << innerHeaderGuard << "_H\n"
+ << "# define SBK_" << innerHeaderGuard << "_H\n\n"
+ << "// Inherited base class:\n";
- int maxOverrides = 0;
- for (const auto &func : metaClass->functions()) {
- const auto generation = functionGeneration(func);
- writeFunction(s, func, generation);
- // PYSIDE-803: Build a boolean cache for unused overrides.
- if (generation.testFlag(FunctionGenerationFlag::VirtualMethod))
- maxOverrides++;
- }
- if (!maxOverrides)
- maxOverrides = 1;
-
- //destructor
- // PYSIDE-504: When C++ 11 is used, then the destructor must always be declared.
- // See abstractmetalang.cpp, determineCppWrapper() and generator.h for further
- // reference.
- if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor() || alwaysGenerateDestructor) {
- if (avoidProtectedHack() && metaClass->hasPrivateDestructor())
- s << "// C++11: need to declare (unimplemented) destructor because "
- "the base class destructor is private.\n";
- s << '~' << wrapperName << "();\n";
+ writeWrapperClassDeclaration(s, wrapperName, classContext);
+
+ s << "# endif // SBK_" << innerHeaderGuard << "_H\n\n";
+}
+
+void HeaderGenerator::writeWrapperClassDeclaration(TextStream &s,
+ const QString &wrapperName,
+ const GeneratorContext &classContext) const
+{
+ const AbstractMetaClassCPtr metaClass = classContext.metaClass();
+ const auto typeEntry = metaClass->typeEntry();
+ InheritedOverloadSet inheritedOverloads;
+
+ // write license comment
+ s << licenseComment();
+
+ // Class
+ s << "class " << wrapperName
+ << " : public " << metaClass->qualifiedCppName()
+ << "\n{\npublic:\n" << indent
+ << wrapperName << "(const " << wrapperName << " &) = delete;\n"
+ << wrapperName << "& operator=(const " << wrapperName << " &) = delete;\n"
+ << wrapperName << '(' << wrapperName << " &&) = delete;\n"
+ << wrapperName << "& operator=(" << wrapperName << " &&) = delete;\n\n";
+
+ // Make protected enums accessible
+ if (avoidProtectedHack()) {
+ recurseClassHierarchy(metaClass, [&s] (const AbstractMetaClassCPtr &metaClass) {
+ writeProtectedEnums(s, metaClass);
+ return false;
+ });
+ }
+
+ if (avoidProtectedHack() && metaClass->hasProtectedFields()) {
+ s << "\n// Make protected fields accessible\n";
+ const QString name = metaClass->qualifiedCppName();
+ for (const auto &f : metaClass->fields()) {
+ if (f.isProtected())
+ s << "using " << name << "::" << f.originalName() << ";\n";
}
+ s << '\n';
+ }
- writeClassCodeSnips(s, typeEntry->codeSnips(),
- TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode,
- classContext);
+ int maxOverrides = 0;
+ for (const auto &func : metaClass->functions()) {
+ const auto generation = functionGeneration(func);
+ writeFunction(s, func, &inheritedOverloads, generation);
+ // PYSIDE-803: Build a boolean cache for unused overrides.
+ if (generation.testFlag(FunctionGenerationFlag::VirtualMethod))
+ maxOverrides++;
+ }
+ if (!maxOverrides)
+ maxOverrides = 1;
+
+ //destructor
+ // PYSIDE-504: When C++ 11 is used, then the destructor must always be declared.
+ if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()
+ || alwaysGenerateDestructorDeclaration()) {
+ if (avoidProtectedHack() && metaClass->hasPrivateDestructor())
+ s << "// C++11: need to declare (unimplemented) destructor because "
+ "the base class destructor is private.\n";
+ s << '~' << wrapperName << "()";
+ if (metaClass->hasVirtualDestructor())
+ s << " override";
+ s << ";\n";
+ }
+
+ writeClassCodeSnips(s, typeEntry->codeSnips(),
+ TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode,
+ classContext);
- if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
- && usePySideExtensions() && metaClass->isQObject()) {
- s << outdent << "public:\n" << indent <<
-R"(int qt_metacall(QMetaObject::Call call, int id, void **args) override;
+ if (shouldGenerateMetaObjectFunctions(metaClass)) {
+ s << R"(
+const ::QMetaObject * metaObject() const override;
+int qt_metacall(QMetaObject::Call call, int id, void **args) override;
void *qt_metacast(const char *_clname) override;
)";
- }
+ }
- if (!m_inheritedOverloads.isEmpty()) {
- s << "// Inherited overloads, because the using keyword sux\n";
- for (const auto &func : qAsConst(m_inheritedOverloads))
- writeMemberFunctionWrapper(s, func);
- m_inheritedOverloads.clear();
- }
+ if (!inheritedOverloads.isEmpty()) {
+ s << "// Inherited overloads, because the using keyword sux\n";
+ for (const auto &func : std::as_const(inheritedOverloads))
+ writeMemberFunctionWrapper(s, func);
+ }
- if (usePySideExtensions())
- s << "static void pysideInitQtMetaTypes();\n";
+ if (usePySideExtensions())
+ s << "static void pysideInitQtMetaTypes();\n";
- s << "void resetPyMethodCache();\n"
- << outdent << "private:\n" << indent
- << "mutable bool m_PyMethodCache[" << maxOverrides << "];\n"
- << outdent << "};\n\n";
- if (!innerHeaderGuard.isEmpty())
- s << "# endif // SBK_" << innerHeaderGuard << "_H\n\n";
+ s << "void resetPyMethodCache();\n"
+ << outdent << "private:\n" << indent;
- // PYSIDE-500: Use also includes for inherited wrapper classes, because
- // without the protected hack, we sometimes need to cast inherited wrappers.
- // But we don't use multiple include files. Instead, they are inserted as recursive
- // headers. This keeps the file structure as simple as before the enhanced inheritance.
- metaClass = metaClass->baseClass();
- if (!metaClass || !avoidProtectedHack())
- break;
- classContext = contextForClass(metaClass);
- wrapperName = classContext.effectiveClassName();
- innerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper();
+ if (!metaClass->userAddedPythonOverrides().isEmpty()) {
+ for (const auto &f : metaClass->userAddedPythonOverrides())
+ s << functionSignature(f, {}, {}, Generator::OriginalTypeDescription) << ";\n";
+ s << '\n';
}
- s << "#endif // SBK_" << outerHeaderGuard << "_H\n\n";
+ s << "mutable bool m_PyMethodCache[" << maxOverrides << "];\n"
+ << outdent << "};\n\n";
}
// Write an inline wrapper around a function
@@ -195,8 +293,6 @@ void HeaderGenerator::writeMemberFunctionWrapper(TextStream &s,
{
Q_ASSERT(!func->isConstructor() && !func->isOperatorOverload());
s << "inline ";
- if (func->isStatic())
- s << "static ";
s << functionSignature(func, {}, postfix, Generator::OriginalTypeDescription)
<< " { ";
if (!func->isVoid())
@@ -217,9 +313,9 @@ void HeaderGenerator::writeMemberFunctionWrapper(TextStream &s,
s << ", ";
const AbstractMetaArgument &arg = arguments.at(i);
const auto &type = arg.type();
- const TypeEntry *enumTypeEntry = nullptr;
+ TypeEntryCPtr enumTypeEntry;
if (type.isFlags())
- enumTypeEntry = static_cast<const FlagsTypeEntry *>(type.typeEntry())->originator();
+ enumTypeEntry = std::static_pointer_cast<const FlagsTypeEntry>(type.typeEntry())->originator();
else if (type.isEnum())
enumTypeEntry = type.typeEntry();
if (enumTypeEntry) {
@@ -234,7 +330,8 @@ void HeaderGenerator::writeMemberFunctionWrapper(TextStream &s,
}
void HeaderGenerator::writeFunction(TextStream &s, const AbstractMetaFunctionCPtr &func,
- FunctionGeneration generation)
+ InheritedOverloadSet *inheritedOverloads,
+ FunctionGeneration generation) const
{
// do not write copy ctors here.
@@ -254,7 +351,7 @@ void HeaderGenerator::writeFunction(TextStream &s, const AbstractMetaFunctionCPt
}
const bool isVirtual = generation.testFlag(FunctionGenerationFlag::VirtualMethod);
- if (isVirtual || generation.testFlag(FunctionGenerationFlag::QMetaObjectMethod)) {
+ if (isVirtual) {
s << functionSignature(func, {}, {}, Generator::OriginalTypeDescription)
<< " override;\n";
}
@@ -269,7 +366,7 @@ void HeaderGenerator::writeFunction(TextStream &s, const AbstractMetaFunctionCPt
&& !f->isAbstract()
&& !f->isStatic()
&& f->name() == func->name()) {
- m_inheritedOverloads << f;
+ inheritedOverloads->insert(f);
}
}
@@ -279,28 +376,14 @@ void HeaderGenerator::writeFunction(TextStream &s, const AbstractMetaFunctionCPt
}
}
-static void _writeTypeIndexValue(TextStream &s, const QString &variableName,
- int typeIndex)
-{
- s << " " << AlignedField(variableName, 56) << " = " << typeIndex;
-}
-
-static inline void _writeTypeIndexValueLine(TextStream &s,
- const QString &variableName,
- int typeIndex)
-{
- _writeTypeIndexValue(s, variableName, typeIndex);
- s << ",\n";
-}
-
// Find equivalent typedefs "using Foo=QList<int>", "using Bar=QList<int>"
-static const AbstractMetaClass *
+static AbstractMetaClassCPtr
findEquivalentTemplateTypedef(const AbstractMetaClassCList &haystack,
- const AbstractMetaClass *needle)
+ const AbstractMetaClassCPtr &needle)
{
- auto *templateBaseClass = needle->templateBaseClass();
+ auto templateBaseClass = needle->templateBaseClass();
const auto &instantiations = needle->templateBaseClassInstantiations();
- for (auto *candidate : haystack) {
+ for (const auto &candidate : haystack) {
if (candidate->isTypeDef()
&& candidate->templateBaseClass() == templateBaseClass
&& candidate->templateBaseClassInstantiations() == instantiations) {
@@ -310,19 +393,20 @@ static const AbstractMetaClass *
return nullptr;
}
-void HeaderGenerator::writeTypeIndexValueLine(TextStream &s, const ApiExtractorResult &api,
- const TypeEntry *typeEntry)
+void HeaderGenerator::collectTypeEntryTypeIndexes(const ApiExtractorResult &api,
+ const TypeEntryCPtr &typeEntry,
+ IndexValues *indexValues)
{
if (!typeEntry || !typeEntry->generateCode())
return;
- s.setFieldAlignment(QTextStream::AlignLeft);
const int typeIndex = typeEntry->sbkIndex();
- _writeTypeIndexValueLine(s, getTypeIndexVariableName(typeEntry), typeIndex);
+ indexValues->append({getTypeIndexVariableName(typeEntry), typeIndex, {}});
+
if (typeEntry->isComplex()) {
// For a typedef "using Foo=QList<int>", write a type index
// SBK_QLIST_INT besides SBK_FOO which is then matched by function
// argument. Check against duplicate typedefs for the same types.
- const auto *cType = static_cast<const ComplexTypeEntry *>(typeEntry);
+ const auto cType = std::static_pointer_cast<const ComplexTypeEntry>(typeEntry);
if (cType->baseContainerType()) {
auto metaClass = AbstractMetaClass::findClass(api.classes(), cType);
Q_ASSERT(metaClass != nullptr);
@@ -332,20 +416,21 @@ void HeaderGenerator::writeTypeIndexValueLine(TextStream &s, const ApiExtractorR
metaClass) == nullptr) {
const QString indexVariable =
getTypeAlternateTemplateIndexVariableName(metaClass);
- _writeTypeIndexValueLine(s, indexVariable, typeIndex);
+ indexValues->append({indexVariable, typeIndex, {}});
m_alternateTemplateIndexes.append(m_alternateTemplateIndexes);
}
}
}
if (typeEntry->isEnum()) {
- auto ete = static_cast<const EnumTypeEntry *>(typeEntry);
+ auto ete = std::static_pointer_cast<const EnumTypeEntry>(typeEntry);
if (ete->flags())
- writeTypeIndexValueLine(s, api, ete->flags());
+ collectTypeEntryTypeIndexes(api, ete->flags(), indexValues);
}
}
-void HeaderGenerator::writeTypeIndexValueLines(TextStream &s, const ApiExtractorResult &api,
- const AbstractMetaClass *metaClass)
+void HeaderGenerator::collectClassTypeIndexes(const ApiExtractorResult &api,
+ const AbstractMetaClassCPtr &metaClass,
+ IndexValues *indexValues)
{
auto typeEntry = metaClass->typeEntry();
if (!typeEntry->generateCode())
@@ -353,16 +438,16 @@ void HeaderGenerator::writeTypeIndexValueLines(TextStream &s, const ApiExtractor
// enum indices are required for invisible namespaces as well.
for (const AbstractMetaEnum &metaEnum : metaClass->enums()) {
if (!metaEnum.isPrivate())
- writeTypeIndexValueLine(s, api, metaEnum.typeEntry());
+ collectTypeEntryTypeIndexes(api, metaEnum.typeEntry(), indexValues);
}
if (NamespaceTypeEntry::isVisibleScope(typeEntry))
- writeTypeIndexValueLine(s, api, typeEntry);
+ collectTypeEntryTypeIndexes(api, typeEntry, indexValues);
}
// Format the typedefs for the typedef entries to be generated
static void formatTypeDefEntries(TextStream &s)
{
- QList<const TypedefEntry *> entries;
+ QList<TypedefEntryCPtr> entries;
const auto typeDbEntries = TypeDatabase::instance()->typedefEntries();
for (auto it = typeDbEntries.cbegin(), end = typeDbEntries.cend(); it != end; ++it) {
if (it.value()->generateCode() != 0)
@@ -371,76 +456,258 @@ static void formatTypeDefEntries(TextStream &s)
if (entries.isEmpty())
return;
s << "\n// typedef entries\n";
- for (const auto e : entries) {
+ for (const auto &e : entries) {
const QString name = e->qualifiedCppName();
// Fixme: simplify by using nested namespaces in C++ 17.
const auto components = QStringView{name}.split(u"::");
- const int nameSpaceCount = components.size() - 1;
- for (int n = 0; n < nameSpaceCount; ++n)
+ const auto nameSpaceCount = components.size() - 1;
+ for (qsizetype n = 0; n < nameSpaceCount; ++n)
s << "namespace " << components.at(n) << " {\n";
s << "using " << components.constLast() << " = " << e->sourceType() << ";\n";
- for (int n = 0; n < nameSpaceCount; ++n)
+ for (qsizetype n = 0; n < nameSpaceCount; ++n)
s << "}\n";
}
s << '\n';
}
+// Helpers for forward-declaring classes in the module header for the
+// specialization of the SbkType template functions. This is possible if the
+// class does not have inner types or enums which need to be known.
+static bool canForwardDeclare(const AbstractMetaClassCPtr &c)
+{
+ if (c->isNamespace() || !c->enums().isEmpty()
+ || !c->innerClasses().isEmpty() || c->isTypeDef()) {
+ return false;
+ }
+ if (auto encl = c->enclosingClass())
+ return encl->isNamespace();
+ return true;
+}
-bool HeaderGenerator::finishGeneration()
+static void writeForwardDeclaration(TextStream &s, const AbstractMetaClassCPtr &c)
{
- // Generate the main header for this module.
- // This header should be included by binding modules
- // extendind on top of this one.
- QSet<Include> includes;
- QSet<Include> privateIncludes;
- StringStream macrosStream(TextStream::Language::Cpp);
+ Q_ASSERT(!c->isNamespace());
+ const bool isStruct = c->attributes().testFlag(AbstractMetaClass::Struct);
+ s << (isStruct ? "struct " : "class ");
+ // Do not use name as this can be modified/renamed for target lang.
+ const QString qualifiedCppName = c->qualifiedCppName();
+ const auto lastQualifier = qualifiedCppName.lastIndexOf(u':');
+ if (lastQualifier != -1)
+ s << QStringView{qualifiedCppName}.mid(lastQualifier + 1);
+ else
+ s << qualifiedCppName;
+ s << ";\n";
+}
- const auto snips = TypeDatabase::instance()->defaultTypeSystemType()->codeSnips();
- if (!snips.isEmpty()) {
- writeCodeSnips(macrosStream, snips, TypeSystem::CodeSnipPositionDeclaration,
- TypeSystem::TargetLangCode);
+// Helpers for writing out namespaces hierarchically when writing class
+// forward declarations to the module header. Ensure inline namespaces
+// are marked as such (else clang complains) and namespaces are ordered.
+struct NameSpace {
+ AbstractMetaClassCPtr nameSpace;
+ AbstractMetaClassCList classes;
+};
+
+static bool operator<(const NameSpace &n1, const NameSpace &n2)
+{
+ return n1.nameSpace->name() < n2.nameSpace->name();
+}
+
+using NameSpaces = QList<NameSpace>;
+
+static qsizetype indexOf(const NameSpaces &nsps, const AbstractMetaClassCPtr &needle)
+{
+ for (qsizetype i = 0, count = nsps.size(); i < count; ++i) {
+ if (nsps.at(i).nameSpace == needle)
+ return i;
}
+ return -1;
+}
- macrosStream << "// Type indices\nenum : int {\n";
- auto classList = api().classes();
+static void writeNamespaceForwardDeclarationRecursion(TextStream &s, qsizetype idx,
+ const NameSpaces &nameSpaces)
+{
+ auto &root = nameSpaces.at(idx);
+ s << '\n';
+ if (root.nameSpace->isInlineNamespace())
+ s << "inline ";
+ s << "namespace " << root.nameSpace->name() << " {\n" << indent;
+ for (const auto &c : root.classes)
+ writeForwardDeclaration(s, c);
+
+ for (qsizetype i = 0, count = nameSpaces.size(); i < count; ++i) {
+ if (i != idx && nameSpaces.at(i).nameSpace->enclosingClass() == root.nameSpace)
+ writeNamespaceForwardDeclarationRecursion(s, i, nameSpaces);
+ }
+ s << outdent << "}\n";
+}
- std::sort(classList.begin(), classList.end(),
- [](const AbstractMetaClass *a, const AbstractMetaClass *b) {
- return a->typeEntry()->sbkIndex() < b->typeEntry()->sbkIndex();
- });
+static void writeForwardDeclarations(TextStream &s,
+ const AbstractMetaClassCList &classList)
+{
+ NameSpaces nameSpaces;
- for (const AbstractMetaClass *metaClass : classList)
- writeTypeIndexValueLines(macrosStream, api(), metaClass);
+ s << '\n';
+ auto typeSystemEntry = TypeDatabase::instance()->defaultTypeSystemType();
+ if (!typeSystemEntry->namespaceBegin().isEmpty())
+ s << typeSystemEntry->namespaceBegin() << '\n';
+
+ for (const auto &c : classList) {
+ if (auto encl = c->enclosingClass()) {
+ Q_ASSERT(encl->isNamespace());
+ auto idx = indexOf(nameSpaces, encl);
+ if (idx != -1) {
+ nameSpaces[idx].classes.append(c);
+ } else {
+ nameSpaces.append(NameSpace{encl, {c}});
+ for (auto enclNsp = encl->enclosingClass(); enclNsp;
+ enclNsp = enclNsp->enclosingClass()) {
+ idx = indexOf(nameSpaces, enclNsp);
+ if (idx == -1)
+ nameSpaces.append(NameSpace{enclNsp, {}});
+ }
+ }
+ } else {
+ writeForwardDeclaration(s, c);
+ }
+ }
+
+ std::sort(nameSpaces.begin(), nameSpaces.end());
+
+ // Recursively write out namespaces starting at the root elements.
+ for (qsizetype i = 0, count = nameSpaces.size(); i < count; ++i) {
+ const auto &nsp = nameSpaces.at(i);
+ if (nsp.nameSpace->enclosingClass() == nullptr)
+ writeNamespaceForwardDeclarationRecursion(s, i, nameSpaces);
+ }
+
+ if (!typeSystemEntry->namespaceEnd().isEmpty())
+ s << typeSystemEntry->namespaceEnd() << '\n';
+}
+
+// Include parameters required for the module/private module header
+
+using ConditionalIncludeMap = QMap<QString, IncludeGroup>;
+
+static TextStream &operator<<(TextStream &s, const ConditionalIncludeMap &m)
+{
+ for (auto it = m.cbegin(), end = m.cend(); it != end; ++it)
+ s << it.key() << '\n' << it.value() << "#endif\n";
+ return s;
+}
+
+struct ModuleHeaderParameters
+{
+ AbstractMetaClassCList forwardDeclarations;
+ std::set<Include> includes;
+ ConditionalIncludeMap conditionalIncludes;
+ QString typeFunctions;
+};
+
+HeaderGenerator::IndexValues
+ HeaderGenerator::collectTypeIndexes(const AbstractMetaClassCList &classList)
+{
+ IndexValues result;
+
+ for (const auto &metaClass : classList)
+ collectClassTypeIndexes(api(), metaClass, &result);
for (const AbstractMetaEnum &metaEnum : api().globalEnums())
- writeTypeIndexValueLine(macrosStream, api(), metaEnum.typeEntry());
+ collectTypeEntryTypeIndexes(api(), metaEnum.typeEntry(), &result);
// Write the smart pointer define indexes.
int smartPointerCountIndex = getMaxTypeIndex();
int smartPointerCount = 0;
for (const auto &smp : api().instantiatedSmartPointers()) {
QString indexName = getTypeIndexVariableName(smp.type);
- _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex);
- macrosStream << ", // " << smp.type.cppSignature() << '\n';
+ result.append({indexName, smartPointerCountIndex, smp.type.cppSignature()});
// Add a the same value for const pointees (shared_ptr<const Foo>).
const auto ptrName = smp.type.typeEntry()->entryName();
- int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive);
+ const auto pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive);
if (pos >= 0) {
- indexName.insert(pos + ptrName.size() + 1, u"CONST"_s);
- _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex);
- macrosStream << ", // (const)\n";
+ indexName.insert(pos + ptrName.size() + 1, u"const"_s);
+ result.append({indexName, smartPointerCountIndex, "(const)"_L1});
}
++smartPointerCountIndex;
++smartPointerCount;
}
+ result.append({"SBK_"_L1 + moduleName() + "_IDX_COUNT"_L1,
+ getMaxTypeIndex() + smartPointerCount, {}});
+ return result;
+}
+
+HeaderGenerator::IndexValues HeaderGenerator::collectConverterIndexes() const
+{
+ IndexValues result;
+ const auto &primitives = primitiveTypes();
+ int pCount = 0;
+ for (const auto &ptype : primitives) {
+ // Note: do not generate indices for typedef'd primitive types as
+ // they'll use the primitive type converters instead, so we
+ // don't need to create any other.
+ if (ptype->generateCode() && ptype->customConversion() != nullptr)
+ result.append({getTypeIndexVariableName(ptype), pCount++, {}});
+ }
+
+ for (const AbstractMetaType &container : api().instantiatedContainers()) {
+ result.append({getTypeIndexVariableName(container),
+ pCount++, container.cppSignature()});
+ }
+
+ // Because on win32 the compiler will not accept a zero length array.
+ if (pCount == 0)
+ pCount++;
+ result.append({"SBK_"_L1 + moduleName() + "_CONVERTERS_IDX_COUNT"_L1,
+ pCount, {}});
+ return result;
+}
+
+// PYSIDE-2404: Write the enums in unchanged case for reuse in type imports.
+// For conpatibility, we create them in uppercase, too and with
+// doubled index for emulating the former type-only case.
+//
+// FIXME: Remove in PySide 7. (See the note in `parser.py`)
+//
+static IndexValue typeIndexUpper(struct IndexValue const &ti)
+{
+ QString modi = ti.name.toUpper();
+ if (modi == ti.name)
+ modi = u"// "_s + modi;
+ return {modi, ti.value * 2, ti.comment};
+}
+
+bool HeaderGenerator::finishGeneration()
+{
+ // Generate the main header for this module. This header should be included
+ // by binding modules extending on top of this one.
+ ModuleHeaderParameters parameters;
+ ModuleHeaderParameters privateParameters;
+ StringStream macrosStream(TextStream::Language::Cpp);
+
+ const auto snips = TypeDatabase::instance()->defaultTypeSystemType()->codeSnips();
+ writeModuleCodeSnips(macrosStream, snips, TypeSystem::CodeSnipPositionDeclaration,
+ TypeSystem::TargetLangCode);
+
+ auto classList = api().classes();
+
+ std::sort(classList.begin(), classList.end(),
+ [](const AbstractMetaClassCPtr &a, const AbstractMetaClassCPtr &b) {
+ return a->typeEntry()->sbkIndex() < b->typeEntry()->sbkIndex();
+ });
+
+ const auto typeIndexes = collectTypeIndexes(classList);
- _writeTypeIndexValue(macrosStream,
- u"SBK_"_s + moduleName() + u"_IDX_COUNT"_s,
- getMaxTypeIndex() + smartPointerCount);
- macrosStream << "\n};\n";
+ macrosStream << "\n// Type indices\nenum [[deprecated]] : int {\n";
+ for (const auto &ti : typeIndexes)
+ macrosStream << typeIndexUpper(ti);
+ macrosStream << "};\n";
+
+ macrosStream << "\n// Type indices\nenum : int {\n";
+ for (const auto &ti : typeIndexes)
+ macrosStream << ti;
+ macrosStream << "};\n\n";
macrosStream << "// This variable stores all Python types exported by this module.\n";
- macrosStream << "extern PyTypeObject **" << cppApiVariableName() << ";\n\n";
+ macrosStream << "extern Shiboken::Module::TypeInitStruct *" << cppApiVariableName() << ";\n\n";
macrosStream << "// This variable stores the Python module object exported by this module.\n";
macrosStream << "extern PyObject *" << pythonModuleObjectName() << ";\n\n";
macrosStream << "// This variable stores all type converters exported by this module.\n";
@@ -448,32 +715,16 @@ bool HeaderGenerator::finishGeneration()
// TODO-CONVERTER ------------------------------------------------------------------------------
// Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex().
- macrosStream << "// Converter indices\nenum : int {\n";
- const PrimitiveTypeEntryList &primitives = primitiveTypes();
- int pCount = 0;
- for (const PrimitiveTypeEntry *ptype : primitives) {
- /* Note: do not generate indices for typedef'd primitive types
- * as they'll use the primitive type converters instead, so we
- * don't need to create any other.
- */
- if (!ptype->generateCode() || !ptype->customConversion())
- continue;
+ const auto converterIndexes = collectConverterIndexes();
+ macrosStream << "// Converter indices\nenum [[deprecated]] : int {\n";
+ for (const auto &ci : converterIndexes)
+ macrosStream << typeIndexUpper(ci);
+ macrosStream << "};\n\n";
- _writeTypeIndexValueLine(macrosStream, getTypeIndexVariableName(ptype), pCount++);
- }
-
- for (const AbstractMetaType &container : api().instantiatedContainers()) {
- _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount);
- macrosStream << ", // " << container.cppSignature() << '\n';
- pCount++;
- }
-
- // Because on win32 the compiler will not accept a zero length array.
- if (pCount == 0)
- pCount++;
- _writeTypeIndexValue(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT")
- .arg(moduleName()), pCount);
- macrosStream << "\n};\n";
+ macrosStream << "// Converter indices\nenum : int {\n";
+ for (const auto &ci : converterIndexes)
+ macrosStream << ci;
+ macrosStream << "};\n";
formatTypeDefEntries(macrosStream);
@@ -481,36 +732,46 @@ bool HeaderGenerator::finishGeneration()
macrosStream << "// Macros for type check\n";
- StringStream typeFunctions(TextStream::Language::Cpp);
- StringStream privateTypeFunctions(TextStream::Language::Cpp);
- if (usePySideExtensions()) {
- typeFunctions << "QT_WARNING_PUSH\n";
- typeFunctions << "QT_WARNING_DISABLE_DEPRECATED\n";
- }
+ TextStream typeFunctions(&parameters.typeFunctions, TextStream::Language::Cpp);
+ TextStream privateTypeFunctions(&privateParameters.typeFunctions, TextStream::Language::Cpp);
+
for (const AbstractMetaEnum &cppEnum : api().globalEnums()) {
if (!cppEnum.isAnonymous()) {
- includes << cppEnum.typeEntry()->include();
+ const auto te = cppEnum.typeEntry();
+ if (te->hasConfigCondition())
+ parameters.conditionalIncludes[te->configCondition()].append(te->include());
+ else
+ parameters.includes.insert(cppEnum.typeEntry()->include());
writeSbkTypeFunction(typeFunctions, cppEnum);
}
}
StringStream protEnumsSurrogates(TextStream::Language::Cpp);
- for (auto metaClass : classList) {
- const TypeEntry *classType = metaClass->typeEntry();
+ for (const auto &metaClass : classList) {
+ const auto classType = metaClass->typeEntry();
if (!shouldGenerate(classType))
continue;
- //Includes
+ // Includes
const bool isPrivate = classType->isPrivate();
- auto &includeList = isPrivate ? privateIncludes : includes;
- includeList << classType->include();
+ auto &par = isPrivate ? privateParameters : parameters;
+ const auto classInclude = classType->include();
+ const bool hasConfigCondition = classType->hasConfigCondition();
+ if (leanHeaders() && canForwardDeclare(metaClass))
+ par.forwardDeclarations.append(metaClass);
+ else if (hasConfigCondition)
+ par.conditionalIncludes[classType->configCondition()].append(classInclude);
+ else
+ par.includes.insert(classInclude);
+
auto &typeFunctionsStr = isPrivate ? privateTypeFunctions : typeFunctions;
+ ConfigurableScope configScope(typeFunctionsStr, classType);
for (const AbstractMetaEnum &cppEnum : metaClass->enums()) {
if (cppEnum.isAnonymous() || cppEnum.isPrivate())
continue;
- EnumTypeEntry *enumType = cppEnum.typeEntry();
- includeList << enumType->include();
+ if (const auto inc = cppEnum.typeEntry()->include(); inc != classInclude)
+ par.includes.insert(inc);
writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
writeSbkTypeFunction(typeFunctionsStr, cppEnum);
}
@@ -520,12 +781,9 @@ bool HeaderGenerator::finishGeneration()
}
for (const auto &smp : api().instantiatedSmartPointers()) {
- const TypeEntry *classType = smp.type.typeEntry();
- includes << classType->include();
+ parameters.includes.insert(smp.type.typeEntry()->include());
writeSbkTypeFunction(typeFunctions, smp.type);
}
- if (usePySideExtensions())
- typeFunctions << "QT_WARNING_POP\n";
const QString moduleHeaderDir = outputDirectory() + u'/'
+ subDirectoryForPackage(packageName()) + u'/';
@@ -548,34 +806,40 @@ bool HeaderGenerator::finishGeneration()
}
s << "#include <sbkpython.h>\n";
+ s << "#include <sbkmodule.h>\n";
s << "#include <sbkconverter.h>\n";
QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports();
if (!requiredTargetImports.isEmpty()) {
s << "// Module Includes\n";
- for (const QString &requiredModule : qAsConst(requiredTargetImports))
+ for (const QString &requiredModule : std::as_const(requiredTargetImports))
s << "#include <" << getModuleHeaderFileName(requiredModule) << ">\n";
s<< '\n';
}
s << "// Bound library includes\n";
- for (const Include &include : qAsConst(includes))
+ for (const Include &include : parameters.includes)
s << include;
+ s << parameters.conditionalIncludes;
+
+ if (leanHeaders()) {
+ writeForwardDeclarations(s, parameters.forwardDeclarations);
+ } else {
+ if (!primitiveTypes().isEmpty()) {
+ s << "// Conversion Includes - Primitive Types\n";
+ const auto &primitiveTypeList = primitiveTypes();
+ for (const auto &ptype : primitiveTypeList)
+ s << ptype->include();
+ s<< '\n';
+ }
- if (!primitiveTypes().isEmpty()) {
- s << "// Conversion Includes - Primitive Types\n";
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *ptype : primitiveTypeList)
- s << ptype->include();
- s<< '\n';
- }
-
- if (!containerTypes().isEmpty()) {
- s << "// Conversion Includes - Container Types\n";
- const ContainerTypeEntryList &containerTypeList = containerTypes();
- for (const ContainerTypeEntry *ctype : containerTypeList)
- s << ctype->include();
- s<< '\n';
+ if (!containerTypes().isEmpty()) {
+ s << "// Conversion Includes - Container Types\n";
+ const ContainerTypeEntryCList &containerTypeList = containerTypes();
+ for (const auto &ctype : containerTypeList)
+ s << ctype->include();
+ s<< '\n';
+ }
}
s << macrosStream.toString() << '\n';
@@ -585,25 +849,21 @@ bool HeaderGenerator::finishGeneration()
<< protEnumsSurrogates.toString() << '\n';
}
- s << "namespace Shiboken\n{\n\n"
- << "// PyType functions, to get the PyObjectType for a type T\n"
- << typeFunctions.toString() << '\n'
- << "} // namespace Shiboken\n\n"
- << "#endif // " << includeShield << "\n\n";
+ writeTypeFunctions(s, parameters.typeFunctions);
+
+ s << "#endif // " << includeShield << "\n\n";
file.done();
- if (hasPrivateClasses()) {
- writePrivateHeader(moduleHeaderDir, includeShield,
- privateIncludes, privateTypeFunctions.toString());
- }
+ if (hasPrivateClasses())
+ writePrivateHeader(moduleHeaderDir, includeShield, privateParameters);
+
return true;
}
void HeaderGenerator::writePrivateHeader(const QString &moduleHeaderDir,
const QString &publicIncludeShield,
- const QSet<Include> &privateIncludes,
- const QString &privateTypeFunctions)
+ const ModuleHeaderParameters &parameters)
{
// Write includes and type functions of private classes
@@ -611,63 +871,90 @@ void HeaderGenerator::writePrivateHeader(const QString &moduleHeaderDir,
TextStream &ps = privateFile.stream;
ps.setLanguage(TextStream::Language::Cpp);
QString privateIncludeShield =
- publicIncludeShield.left(publicIncludeShield.size() - 2)
- + QStringLiteral("_P_H");
+ publicIncludeShield.left(publicIncludeShield.size() - 2) + "_P_H"_L1;
ps << licenseComment()<< "\n\n";
ps << "#ifndef " << privateIncludeShield << '\n';
ps << "#define " << privateIncludeShield << "\n\n";
- for (const Include &include : qAsConst(privateIncludes))
+ for (const Include &include : parameters.includes)
ps << include;
+ ps << parameters.conditionalIncludes;
ps << '\n';
+ if (leanHeaders())
+ writeForwardDeclarations(ps, parameters.forwardDeclarations);
+
+ writeTypeFunctions(ps, parameters.typeFunctions);
+
+ ps << "#endif\n";
+ privateFile.done();
+}
+
+void HeaderGenerator::writeTypeFunctions(TextStream &s, const QString &typeFunctions)
+{
+ if (typeFunctions.isEmpty())
+ return;
+
if (usePySideExtensions())
- ps << "QT_WARNING_PUSH\nQT_WARNING_DISABLE_DEPRECATED\n";
+ s << "QT_WARNING_PUSH\nQT_WARNING_DISABLE_DEPRECATED\n";
- ps << "namespace Shiboken\n{\n\n"
+ s << "namespace Shiboken\n{\n\n"
<< "// PyType functions, to get the PyObjectType for a type T\n"
- << privateTypeFunctions << '\n'
+ << typeFunctions << '\n'
<< "} // namespace Shiboken\n\n";
if (usePySideExtensions())
- ps << "QT_WARNING_POP\n";
-
- ps << "#endif\n";
- privateFile.done();
+ s << "QT_WARNING_POP\n";
}
-void HeaderGenerator::writeProtectedEnumSurrogate(TextStream &s, const AbstractMetaEnum &cppEnum) const
+void HeaderGenerator::writeProtectedEnumSurrogate(TextStream &s, const AbstractMetaEnum &cppEnum)
{
if (avoidProtectedHack() && cppEnum.isProtected())
s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};\n";
}
-void HeaderGenerator::writeSbkTypeFunction(TextStream &s, const AbstractMetaEnum &cppEnum) const
+void HeaderGenerator::writeSbkTypeFunction(TextStream &s, const AbstractMetaEnum &cppEnum)
{
const QString enumName = avoidProtectedHack() && cppEnum.isProtected()
? protectedEnumSurrogateName(cppEnum)
: cppEnum.qualifiedCppName();
+ const auto te = cppEnum.typeEntry();
+ ConfigurableScope configScope(s, te);
+ s << "template<> inline PyTypeObject *SbkType< " << m_gsp << enumName << " >() ";
+ s << "{ return " << cpythonTypeNameExt(te) << "; }\n";
- s << "template<> inline PyTypeObject *SbkType< ::" << enumName << " >() ";
- s << "{ return " << cpythonTypeNameExt(cppEnum.typeEntry()) << "; }\n";
-
- FlagsTypeEntry *flag = cppEnum.typeEntry()->flags();
+ const auto flag = cppEnum.typeEntry()->flags();
if (flag) {
- s << "template<> inline PyTypeObject *SbkType< ::" << flag->name() << " >() "
+ s << "template<> inline PyTypeObject *SbkType< " << m_gsp << flag->name() << " >() "
<< "{ return " << cpythonTypeNameExt(flag) << "; }\n";
}
}
-void HeaderGenerator::writeSbkTypeFunction(TextStream &s, const AbstractMetaClass *cppClass)
+void HeaderGenerator::writeSbkTypeFunction(TextStream &s, const AbstractMetaClassCPtr &cppClass)
{
- s << "template<> inline PyTypeObject *SbkType< ::" << cppClass->qualifiedCppName() << " >() "
- << "{ return reinterpret_cast<PyTypeObject *>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n";
+ s << "template<> inline PyTypeObject *SbkType< "
+ << getFullTypeName(cppClass) << " >() "
+ << "{ return " << cpythonTypeNameExt(cppClass->typeEntry()) << "; }\n";
}
void HeaderGenerator::writeSbkTypeFunction(TextStream &s, const AbstractMetaType &metaType)
{
- s << "template<> inline PyTypeObject *SbkType< ::" << metaType.cppSignature() << " >() "
+ s << "template<> inline PyTypeObject *SbkType< "
+ << m_gsp << metaType.cppSignature() << " >() "
<< "{ return " << cpythonTypeNameExt(metaType) << "; }\n";
}
+
+void HeaderGenerator::writeModuleCodeSnips(TextStream &s, const CodeSnipList &codeSnips,
+ TypeSystem::CodeSnipPosition position,
+ TypeSystem::Language language) const
+{
+ if (!codeSnips.isEmpty()) {
+ try {
+ writeCodeSnips(s, codeSnips, position, language);
+ } catch (const std::exception &e) {
+ throw Exception(msgSnippetError("module header of "_L1 + moduleName(), e.what()));
+ }
+ }
+}
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.h b/sources/shiboken6/generator/shiboken/headergenerator.h
index a02cc5235..03b98e743 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.h
+++ b/sources/shiboken6/generator/shiboken/headergenerator.h
@@ -6,10 +6,14 @@
#include "shibokengenerator.h"
#include "include.h"
+#include "modifications_typedefs.h"
+#include <QtCore/QList>
#include <QtCore/QSet>
+struct IndexValue;
class AbstractMetaFunction;
+struct ModuleHeaderParameters;
/**
* The HeaderGenerator generate the declarations of C++ bindings classes.
@@ -17,11 +21,9 @@ class AbstractMetaFunction;
class HeaderGenerator : public ShibokenGenerator
{
public:
- OptionDescriptions options() const override { return OptionDescriptions(); }
-
const char *name() const override { return "Header generator"; }
- static QString headerFileNameForContext(const GeneratorContext &context);
+ static const char *protectedHackDefine;
protected:
QString fileNameForContext(const GeneratorContext &context) const override;
@@ -29,26 +31,44 @@ protected:
bool finishGeneration() override;
private:
- void writeCopyCtor(TextStream &s, const AbstractMetaClass *metaClass) const;
- void writeFunction(TextStream &s, const AbstractMetaFunctionCPtr &func,
- FunctionGeneration generation);
- void writeSbkTypeFunction(TextStream &s, const AbstractMetaEnum &cppEnum) const;
- static void writeSbkTypeFunction(TextStream &s, const AbstractMetaClass *cppClass) ;
- static void writeSbkTypeFunction(TextStream &s, const AbstractMetaType &metaType) ;
- void writeTypeIndexValueLine(TextStream &s, const ApiExtractorResult &api,
- const TypeEntry *typeEntry);
- void writeTypeIndexValueLines(TextStream &s, const ApiExtractorResult &api,
- const AbstractMetaClass *metaClass);
- void writeProtectedEnumSurrogate(TextStream &s, const AbstractMetaEnum &cppEnum) const;
+ using InheritedOverloadSet = QSet<AbstractMetaFunctionCPtr>;
+ using IndexValues = QList<IndexValue>;
+
+ IndexValues collectTypeIndexes(const AbstractMetaClassCList &classList);
+ IndexValues collectConverterIndexes() const;
+
+ static void writeCopyCtor(TextStream &s, const AbstractMetaClassCPtr &metaClass);
+ void writeFunction(TextStream &s,
+ const AbstractMetaFunctionCPtr &func,
+ InheritedOverloadSet *inheritedOverloads,
+ FunctionGeneration generation) const;
+ static void writeSbkTypeFunction(TextStream &s, const AbstractMetaEnum &cppEnum);
+ static void writeSbkTypeFunction(TextStream &s, const AbstractMetaClassCPtr &cppClass);
+ static void writeSbkTypeFunction(TextStream &s, const AbstractMetaType &metaType);
+ void collectTypeEntryTypeIndexes(const ApiExtractorResult &api,
+ const TypeEntryCPtr &typeEntry,
+ IndexValues *indexValues);
+ void collectClassTypeIndexes(const ApiExtractorResult &api,
+ const AbstractMetaClassCPtr &metaClass,
+ IndexValues *indexValues);
+ static void writeProtectedEnumSurrogate(TextStream &s, const AbstractMetaEnum &cppEnum);
void writeMemberFunctionWrapper(TextStream &s,
const AbstractMetaFunctionCPtr &func,
const QString &postfix = {}) const;
void writePrivateHeader(const QString &moduleHeaderDir,
const QString &publicIncludeShield,
- const QSet<Include> &privateIncludes,
- const QString &privateTypeFunctions);
+ const ModuleHeaderParameters &parameters);
+ static void writeTypeFunctions(TextStream &s, const QString &typeFunctions);
+ void writeWrapperClassDeclaration(TextStream &s,
+ const QString &wrapperName,
+ const GeneratorContext &classContext) const;
+ void writeWrapperClass(TextStream &s, const QString &wrapperName, const GeneratorContext &classContext) const;
+ void writeInheritedWrapperClassDeclaration(TextStream &s,
+ const GeneratorContext &classContext) const;
+ void writeModuleCodeSnips(TextStream &s, const CodeSnipList &codeSnips,
+ TypeSystem::CodeSnipPosition position,
+ TypeSystem::Language language) const;
- QSet<AbstractMetaFunctionCPtr> m_inheritedOverloads;
AbstractMetaClassCList m_alternateTemplateIndexes;
};
diff --git a/sources/shiboken6/generator/shiboken/overloaddata.cpp b/sources/shiboken6/generator/shiboken/overloaddata.cpp
index dff5628bf..c28fcdc1a 100644
--- a/sources/shiboken6/generator/shiboken/overloaddata.cpp
+++ b/sources/shiboken6/generator/shiboken/overloaddata.cpp
@@ -16,7 +16,6 @@
#include "pytypenames.h"
#include "textstream.h"
#include "exception.h"
-#include "messages.h"
#include "qtcompat.h"
@@ -31,16 +30,16 @@ using namespace Qt::StringLiterals;
static QString getTypeName(const AbstractMetaType &type)
{
- const TypeEntry *typeEntry = type.typeEntry();
+ TypeEntryCPtr typeEntry = type.typeEntry();
if (typeEntry->isPrimitive())
- typeEntry = typeEntry->asPrimitive()->basicReferencedTypeEntry();
+ typeEntry = basicReferencedTypeEntry(typeEntry);
QString typeName = typeEntry->name();
if (typeEntry->isContainer()) {
QStringList types;
for (const auto &cType : type.instantiations()) {
- const TypeEntry *typeEntry = cType.typeEntry();
+ TypeEntryCPtr typeEntry = cType.typeEntry();
if (typeEntry->isPrimitive())
- typeEntry = typeEntry->asPrimitive()->basicReferencedTypeEntry();
+ typeEntry = basicReferencedTypeEntry(typeEntry);
types << typeEntry->name();
}
typeName += u'<' + types.join(u',') + u" >"_s;
@@ -55,7 +54,7 @@ static bool typesAreEqual(const AbstractMetaType &typeA, const AbstractMetaType
if (typeA.instantiations().size() != typeB.instantiations().size())
return false;
- for (int i = 0; i < typeA.instantiations().size(); ++i) {
+ for (qsizetype i = 0; i < typeA.instantiations().size(); ++i) {
if (!typesAreEqual(typeA.instantiations().at(i), typeB.instantiations().at(i)))
return false;
}
@@ -126,6 +125,7 @@ using OverloadGraph = Graph<QString>;
void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
{
QHash<QString, OverloadDataList> typeToOverloads;
+ using Edge = std::pair<QString, QString>;
bool checkPyObject = false;
bool checkPySequence = false;
@@ -135,13 +135,13 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
// Primitive types that are not int, long, short,
// char and their respective unsigned counterparts.
- static const QStringList nonIntegerPrimitives{floatT(), doubleT(), boolT()};
+ static const QStringList nonIntegerPrimitives{floatT, doubleT, boolT};
// Signed integer primitive types.
- static const QStringList signedIntegerPrimitives{intT(), shortT(), longT(), longLongT()};
+ static const QStringList signedIntegerPrimitives{intT, shortT, longT, longLongT};
// sort the children overloads
- for (const auto &ov : qAsConst(m_children))
+ for (const auto &ov : std::as_const(m_children))
ov->sortNextOverloads(api);
if (m_children.size() <= 1 || sortByOverloadNumberModification(m_children))
@@ -152,7 +152,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
// with graph sorting using integers.
OverloadGraph graph;
- for (const auto &ov : qAsConst(m_children)) {
+ for (const auto &ov : std::as_const(m_children)) {
const QString typeName = getTypeName(ov->modifiedArgType());
auto it = typeToOverloads.find(typeName);
if (it == typeToOverloads.end()) {
@@ -162,15 +162,15 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
it.value().append(ov);
}
- if (!checkPyObject && typeName == cPyObjectT())
+ if (!checkPyObject && typeName == cPyObjectT)
checkPyObject = true;
- else if (!checkPySequence && typeName == cPySequenceT())
+ else if (!checkPySequence && typeName == cPySequenceT)
checkPySequence = true;
- else if (!checkPyBuffer && typeName == cPyBufferT())
+ else if (!checkPyBuffer && typeName == cPyBufferT)
checkPyBuffer = true;
- else if (!checkQVariant && typeName == qVariantT())
+ else if (!checkQVariant && typeName == qVariantT)
checkQVariant = true;
- else if (!checkQString && typeName == qStringT())
+ else if (!checkQString && typeName == qStringT)
checkQString = true;
for (const auto &instantiation : ov->argType().instantiations()) {
@@ -183,7 +183,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
// as Point must come before the PointF instantiation, or else list<Point> will never
// be called. In the case of primitive types, list<double> must come before list<int>.
if (instantiation.isPrimitive() && (signedIntegerPrimitives.contains(instantiation.name()))) {
- for (const QString &primitive : qAsConst(nonIntegerPrimitives))
+ for (const QString &primitive : std::as_const(nonIntegerPrimitives))
graph.addNode(getImplicitConversionTypeName(ov->argType(), instantiation, nullptr, primitive));
} else {
const auto &funcs = api.implicitConversions(instantiation);
@@ -196,9 +196,9 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
// Create the graph of type dependencies based on implicit conversions.
// All C++ primitive types, add any forgotten type AT THE END OF THIS LIST!
- static const QStringList primitiveTypes{intT(), unsignedIntT(), longT(), unsignedLongT(),
- shortT(), unsignedShortT(), boolT(), unsignedCharT(), charT(), floatT(),
- doubleT(), constCharPtrT()};
+ static const QStringList primitiveTypes{intT, unsignedIntT, longT, unsignedLongT,
+ shortT, unsignedShortT, boolT, unsignedCharT, charT, floatT,
+ doubleT, constCharPtrT};
QStringList foundPrimitiveTypeIds;
for (const auto &p : primitiveTypes) {
@@ -207,13 +207,13 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
}
if (checkPySequence && checkPyObject)
- graph.addEdge(cPySequenceT(), cPyObjectT());
+ graph.addEdge(cPySequenceT, cPyObjectT);
QStringList classesWithIntegerImplicitConversion;
AbstractMetaFunctionCList involvedConversions;
- for (const auto &ov : qAsConst(m_children)) {
+ for (const auto &ov : std::as_const(m_children)) {
const AbstractMetaType &targetType = ov->argType();
const QString targetTypeEntryName = getTypeName(ov->modifiedArgType());
@@ -226,7 +226,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
else
convertibleType = getTypeName(function->arguments().constFirst().type());
- if (convertibleType == intT() || convertibleType == unsignedIntT())
+ if (convertibleType == intT || convertibleType == unsignedIntT)
classesWithIntegerImplicitConversion << targetTypeEntryName;
if (!graph.hasNode(convertibleType))
@@ -241,12 +241,12 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
// Process inheritance relationships
if (targetType.isValue() || targetType.isObject()) {
- auto *te = targetType.typeEntry();
+ const auto te = targetType.typeEntry();
auto metaClass = AbstractMetaClass::findClass(api.classes(), te);
if (!metaClass)
throw Exception(msgArgumentClassNotFound(m_overloads.constFirst(), te));
const auto &ancestors = metaClass->allTypeSystemAncestors();
- for (const AbstractMetaClass *ancestor : ancestors) {
+ for (const auto &ancestor : ancestors) {
QString ancestorTypeName = ancestor->typeEntry()->name();
if (!graph.hasNode(ancestorTypeName))
continue;
@@ -263,7 +263,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
graph.addEdge(convertible, targetTypeEntryName);
if (instantiation.isPrimitive() && (signedIntegerPrimitives.contains(instantiation.name()))) {
- for (const QString &primitive : qAsConst(nonIntegerPrimitives)) {
+ for (const QString &primitive : std::as_const(nonIntegerPrimitives)) {
QString convertibleTypeName =
getImplicitConversionTypeName(ov->argType(), instantiation, nullptr, primitive);
// Avoid cyclic dependency.
@@ -288,28 +288,28 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
if ((checkPySequence || checkPyObject || checkPyBuffer)
- && !targetTypeEntryName.contains(cPyObjectT())
- && !targetTypeEntryName.contains(cPyBufferT())
- && !targetTypeEntryName.contains(cPySequenceT())) {
+ && !targetTypeEntryName.contains(cPyObjectT)
+ && !targetTypeEntryName.contains(cPyBufferT)
+ && !targetTypeEntryName.contains(cPySequenceT)) {
if (checkPySequence) {
// PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeEntryName, cPySequenceT());
+ graph.addEdge(targetTypeEntryName, cPySequenceT);
} else if (checkPyBuffer) {
// PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeEntryName, cPyBufferT());
+ graph.addEdge(targetTypeEntryName, cPyBufferT);
} else {
// Add dependency on PyObject, so its check is the last one (too generic).
- graph.addEdge(targetTypeEntryName, cPyObjectT());
+ graph.addEdge(targetTypeEntryName, cPyObjectT);
}
- } else if (checkQVariant && targetTypeEntryName != qVariantT()) {
- if (!graph.containsEdge(qVariantT(), targetTypeEntryName)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeEntryName, qVariantT());
+ } else if (checkQVariant && targetTypeEntryName != qVariantT) {
+ if (!graph.containsEdge(qVariantT, targetTypeEntryName)) // Avoid cyclic dependency.
+ graph.addEdge(targetTypeEntryName, qVariantT);
} else if (checkQString && ov->argType().isPointer()
- && targetTypeEntryName != qStringT()
- && targetTypeEntryName != qByteArrayT()
- && (!checkPyObject || targetTypeEntryName != cPyObjectT())) {
- if (!graph.containsEdge(qStringT(), targetTypeEntryName)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeEntryName, qStringT());
+ && targetTypeEntryName != qStringT
+ && targetTypeEntryName != qByteArrayT
+ && (!checkPyObject || targetTypeEntryName != cPyObjectT)) {
+ if (!graph.containsEdge(qStringT, targetTypeEntryName)) // Avoid cyclic dependency.
+ graph.addEdge(targetTypeEntryName, qStringT);
}
if (targetType.isEnum()) {
@@ -320,25 +320,36 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
}
// QByteArray args need to be checked after QString args
- if (graph.hasNode(qStringT()) && graph.hasNode(qByteArrayT()))
- graph.addEdge(qStringT(), qByteArrayT());
+ if (graph.hasNode(qStringT) && graph.hasNode(qByteArrayT))
+ graph.addEdge(qStringT, qByteArrayT);
+
+ static const Edge rangeOrder[] =
+ {{doubleT, floatT},
+ {longLongT, longT}, {longLongT, intT}, {intT, shortT},
+ {unsignedLongLongT, unsignedLongT}, {unsignedLongLongT, unsignedT},
+ {unsignedLongLongT, unsignedIntT}, {unsignedT, unsignedShortT}
+ };
+ for (const auto &r : rangeOrder) {
+ if (graph.hasNode(r.first) && graph.hasNode(r.second))
+ graph.addEdge(r.first, r.second);
+ }
- for (const auto &ov : qAsConst(m_children)) {
+ for (const auto &ov : std::as_const(m_children)) {
const AbstractMetaType &targetType = ov->argType();
if (!targetType.isEnum())
continue;
QString targetTypeEntryName = getTypeName(targetType);
// Enum values must precede types implicitly convertible from "int" or "unsigned int".
- for (const QString &implicitFromInt : qAsConst(classesWithIntegerImplicitConversion))
+ for (const QString &implicitFromInt : std::as_const(classesWithIntegerImplicitConversion))
graph.addEdge(targetTypeEntryName, implicitFromInt);
}
// Special case for double(int i) (not tracked by m_generator->implicitConversions
- for (const QString &signedIntegerName : qAsConst(signedIntegerPrimitives)) {
+ for (const QString &signedIntegerName : std::as_const(signedIntegerPrimitives)) {
if (graph.hasNode(signedIntegerName)) {
- for (const QString &nonIntegerName : qAsConst(nonIntegerPrimitives)) {
+ for (const QString &nonIntegerName : std::as_const(nonIntegerPrimitives)) {
if (graph.hasNode(nonIntegerName))
graph.addEdge(nonIntegerName, signedIntegerName);
}
@@ -381,8 +392,7 @@ static std::pair<int, int> getMinMaxArgs(const AbstractMetaFunctionCPtr &func)
int defaultValueIndex = -1;
const auto &arguments = func->arguments();
int argIndex = 0;
- for (qsizetype i = 0, size = arguments.size(); i < size; ++i) {
- const auto &arg = arguments.at(i);
+ for (const auto &arg : arguments) {
if (!arg.isModifiedRemoved()) {
if (defaultValueIndex < 0 && arg.hasDefaultValueExpression())
defaultValueIndex = argIndex;
@@ -463,7 +473,7 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu
{
OverloadDataNodePtr overloadData;
if (!func->isOperatorOverload()) {
- for (const auto &tmp : qAsConst(m_children)) {
+ for (const auto &tmp : std::as_const(m_children)) {
// TODO: 'const char *', 'char *' and 'char' will have the same TypeEntry?
// If an argument have a type replacement, then we should create a new overloaddata
@@ -475,13 +485,13 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu
}
}
- if (overloadData.isNull()) {
+ if (!overloadData) {
const int argpos = argPos() + 1;
overloadData.reset(new OverloadDataNode(func, this, arg, argpos));
m_children.append(overloadData);
}
- return overloadData.data();
+ return overloadData.get();
}
bool OverloadData::hasNonVoidReturnType() const
@@ -604,7 +614,7 @@ const AbstractMetaArgument *OverloadDataNode::overloadArgument(const AbstractMet
bool OverloadDataRootNode::nextArgumentHasDefaultValue() const
{
for (const auto &overloadData : m_children) {
- if (!overloadData->getFunctionWithDefaultValue().isNull())
+ if (overloadData->getFunctionWithDefaultValue())
return true;
}
return false;
@@ -612,20 +622,20 @@ bool OverloadDataRootNode::nextArgumentHasDefaultValue() const
static const OverloadDataRootNode *_findNextArgWithDefault(const OverloadDataRootNode *overloadData)
{
- if (!overloadData->getFunctionWithDefaultValue().isNull())
+ if (overloadData->getFunctionWithDefaultValue())
return overloadData;
const OverloadDataRootNode *result = nullptr;
const OverloadDataList &data = overloadData->children();
for (const auto &odata : data) {
- const auto *tmp = _findNextArgWithDefault(odata.data());
+ const auto *tmp = _findNextArgWithDefault(odata.get());
if (!result || (tmp && result->argPos() > tmp->argPos()))
result = tmp;
}
return result;
}
-const OverloadDataRootNode *OverloadDataRootNode::findNextArgWithDefault()
+const OverloadDataRootNode *OverloadDataRootNode::findNextArgWithDefault() const
{
return _findNextArgWithDefault(this);
}
@@ -641,10 +651,10 @@ bool OverloadDataRootNode::isFinalOccurrence(const AbstractMetaFunctionCPtr &fun
AbstractMetaFunctionCPtr OverloadDataRootNode::getFunctionWithDefaultValue() const
{
- const int argpos = argPos();
+ const qsizetype argpos = argPos();
for (const auto &func : m_overloads) {
- int removedArgs = 0;
- for (int i = 0; i <= argpos + removedArgs; i++) {
+ qsizetype removedArgs = 0;
+ for (qsizetype i = 0; i <= argpos + removedArgs; i++) {
if (func->arguments().at(i).isModifiedRemoved())
removedArgs++;
}
@@ -661,7 +671,7 @@ QList<int> OverloadData::invalidArgumentLengths() const
for (const auto &func : m_overloads) {
const AbstractMetaArgumentList args = func->arguments();
int offset = 0;
- for (int i = 0; i < args.size(); ++i) {
+ for (qsizetype i = 0; i < args.size(); ++i) {
if (func->arguments().at(i).isModifiedRemoved()) {
offset++;
} else {
@@ -691,8 +701,8 @@ int OverloadData::numberOfRemovedArguments(const AbstractMetaFunctionCPtr &func,
{
Q_ASSERT(finalArgPos >= 0);
int removed = 0;
- const int size = func->arguments().size();
- for (int i = 0; i < qMin(size, finalArgPos + removed); ++i) {
+ const auto size = func->arguments().size();
+ for (qsizetype i = 0; i < qMin(size, qsizetype(finalArgPos + removed)); ++i) {
if (func->arguments().at(i).isModifiedRemoved())
++removed;
}
@@ -935,7 +945,7 @@ void OverloadDataRootNode::formatOverloads(QDebug &d) const
if (count < 2)
return;
d << "=(";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
d << '\n';
d << m_overloads.at(i)->signature();
@@ -949,7 +959,7 @@ void OverloadDataRootNode::formatNextOverloadData(QDebug &d) const
d << ", next[" << count << ']';
if (d.verbosity() >= 3) {
d << "=(";
- for (int i = 0; i < count; ++i) {
+ for (qsizetype i = 0; i < count; ++i) {
if (i)
d << '\n';
m_children.at(i)->formatDebug(d);
diff --git a/sources/shiboken6/generator/shiboken/overloaddata.h b/sources/shiboken6/generator/shiboken/overloaddata.h
index 3fc9eef50..875a5a8b5 100644
--- a/sources/shiboken6/generator/shiboken/overloaddata.h
+++ b/sources/shiboken6/generator/shiboken/overloaddata.h
@@ -9,13 +9,14 @@
#include <QtCore/QBitArray>
#include <QtCore/QList>
-#include <QtCore/QSharedPointer>
+
+#include <memory>
QT_FORWARD_DECLARE_CLASS(QDebug)
QT_FORWARD_DECLARE_CLASS(QTextStream)
class OverloadDataNode;
-using OverloadDataNodePtr = QSharedPointer<OverloadDataNode>;
+using OverloadDataNodePtr = std::shared_ptr<OverloadDataNode>;
using OverloadDataList = QList<OverloadDataNodePtr>;
/// The root node of OverloadData. It contains all functions
@@ -45,7 +46,7 @@ public:
AbstractMetaFunctionCPtr getFunctionWithDefaultValue() const;
/// Returns the nearest occurrence, including this instance, of an argument with a default value.
- const OverloadDataRootNode *findNextArgWithDefault();
+ const OverloadDataRootNode *findNextArgWithDefault() const;
bool isFinalOccurrence(const AbstractMetaFunctionCPtr &func) const;
int functionNumber(const AbstractMetaFunctionCPtr &func) const;
diff --git a/sources/shiboken6/generator/shiboken/pytypenames.h b/sources/shiboken6/generator/shiboken/pytypenames.h
index 19bfc55c0..6c7658ff6 100644
--- a/sources/shiboken6/generator/shiboken/pytypenames.h
+++ b/sources/shiboken6/generator/shiboken/pytypenames.h
@@ -6,25 +6,24 @@
#include <QtCore/QString>
-static inline QString pyBoolT() { return QStringLiteral("PyBool"); }
-static inline QString pyFloatT() { return QStringLiteral("PyFloat"); }
-static inline QString pyIntT() { return QStringLiteral("PyLong"); }
-static inline QString pyLongT() { return QStringLiteral("PyLong"); }
-static inline QString pyObjectT() { return QStringLiteral("object"); }
-static inline QString pyStrT() { return QStringLiteral("str"); }
+constexpr auto pyBoolT = QLatin1StringView ("PyBool");
+constexpr auto pyFloatT = QLatin1StringView ("PyFloat");
+constexpr auto pyLongT = QLatin1StringView ("PyLong");
+constexpr auto pyObjectT = QLatin1StringView ("object");
+constexpr auto pyStrT = QLatin1StringView ("str");
// PYSIDE-1499: A custom type determined by existence of an `__fspath__` attribute.
-static inline QString pyPathLikeT() { return QStringLiteral("PyPathLike"); }
+constexpr auto pyPathLikeT = QLatin1StringView ("PyPathLike");
-static inline QString cPyBufferT() { return QStringLiteral("PyBuffer"); }
-static inline QString cPyListT() { return QStringLiteral("PyList"); }
-static inline QString cPyObjectT() { return QStringLiteral("PyObject"); }
-static inline QString cPySequenceT() { return QStringLiteral("PySequence"); }
-static inline QString cPyTypeObjectT() { return QStringLiteral("PyTypeObject"); }
+constexpr auto cPyBufferT = QLatin1StringView ("PyBuffer");
+constexpr auto cPyListT = QLatin1StringView ("PyList");
+constexpr auto cPyObjectT = QLatin1StringView ("PyObject");
+constexpr auto cPySequenceT = QLatin1StringView ("PySequence");
+constexpr auto cPyTypeObjectT = QLatin1StringView ("PyTypeObject");
// numpy
-static inline QString cPyArrayObjectT() { return QStringLiteral("PyArrayObject"); }
+constexpr auto cPyArrayObjectT = QLatin1StringView ("PyArrayObject");
-static inline QString sbkCharT() { return QStringLiteral("SbkChar"); }
+constexpr auto sbkCharT = QLatin1StringView ("SbkChar");
#endif // PYTYPENAMES_H
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index 264c8cfea..a1417e5d9 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -2,8 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "shibokengenerator.h"
+#include "generatorstrings.h"
+#include "generatorargument.h"
+#include "defaultvalue.h"
+#include "generatorcontext.h"
#include "apiextractorresult.h"
#include "codesnip.h"
+#include "customconversion.h"
#include "ctypenames.h"
#include <abstractmetabuilder.h>
#include <abstractmetaenum.h>
@@ -16,12 +21,12 @@
#include <messages.h>
#include <modifications.h>
#include "overloaddata.h"
+#include <optionsparser.h>
#include "propertyspec.h"
#include "pytypenames.h"
#include <reporthandler.h>
#include <textstream.h>
#include <typedatabase.h>
-#include <abstractmetabuilder.h>
#include <containertypeentry.h>
#include <customtypenentry.h>
#include <enumtypeentry.h>
@@ -29,6 +34,8 @@
#include <namespacetypeentry.h>
#include <primitivetypeentry.h>
#include <pythontypeentry.h>
+#include <smartpointertypeentry.h>
+#include <valuetypeentry.h>
#include <iostream>
@@ -37,43 +44,73 @@
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QRegularExpression>
+
+#include <algorithm>
#include <limits>
#include <memory>
+#include <utility>
using namespace Qt::StringLiterals;
-static const char PARENT_CTOR_HEURISTIC[] = "enable-parent-ctor-heuristic";
-static const char RETURN_VALUE_HEURISTIC[] = "enable-return-value-heuristic";
-static const char DISABLE_VERBOSE_ERROR_MESSAGES[] = "disable-verbose-error-messages";
-static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero";
-static const char USE_OPERATOR_BOOL_AS_NB_NONZERO[] = "use-operator-bool-as-nb_nonzero";
-static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics";
-static const char NO_IMPLICIT_CONVERSIONS[] = "no-implicit-conversions";
-
-const QString CPP_ARG = u"cppArg"_s;
-const QString CPP_ARG_REMOVED = u"removed_cppArg"_s;
-const QString CPP_RETURN_VAR = u"cppResult"_s;
-const QString CPP_SELF_VAR = u"cppSelf"_s;
-const QString NULL_PTR = u"nullptr"_s;
-const QString PYTHON_ARG = u"pyArg"_s;
-const QString PYTHON_ARGS = u"pyArgs"_s;
-const QString PYTHON_OVERRIDE_VAR = u"pyOverride"_s;
-const QString PYTHON_RETURN_VAR = u"pyResult"_s;
-const QString PYTHON_TO_CPP_VAR = u"pythonToCpp"_s;
-const QString SMART_POINTER_GETTER = u"kSmartPointerGetter"_s;
-
-const QString CONV_RULE_OUT_VAR_SUFFIX = u"_out"_s;
-const QString BEGIN_ALLOW_THREADS =
- u"PyThreadState *_save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS"_s;
-const QString END_ALLOW_THREADS = u"PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS"_s;
+static constexpr auto PARENT_CTOR_HEURISTIC = "enable-parent-ctor-heuristic"_L1;
+static constexpr auto RETURN_VALUE_HEURISTIC = "enable-return-value-heuristic"_L1;
+static constexpr auto DISABLE_VERBOSE_ERROR_MESSAGES = "disable-verbose-error-messages"_L1;
+static constexpr auto USE_ISNULL_AS_NB_BOOL = "use-isnull-as-nb-bool"_L1;
+// FIXME PYSIDE 7: Remove USE_ISNULL_AS_NB_NONZERO/USE_OPERATOR_BOOL_AS_NB_NONZERO
+static constexpr auto USE_ISNULL_AS_NB_NONZERO = "use-isnull-as-nb_nonzero"_L1;
+static constexpr auto USE_OPERATOR_BOOL_AS_NB_BOOL = "use-operator-bool-as-nb-bool"_L1;
+static constexpr auto USE_OPERATOR_BOOL_AS_NB_NONZERO = "use-operator-bool-as-nb-nonzero"_L1;
+static constexpr auto WRAPPER_DIAGNOSTICS = "wrapper-diagnostics"_L1;
+static constexpr auto NO_IMPLICIT_CONVERSIONS = "no-implicit-conversions"_L1;
+static constexpr auto LEAN_HEADERS = "lean-headers"_L1;
+
+QString CPP_ARG_N(int i)
+{
+ return CPP_ARG + QString::number(i);
+}
+
+constexpr auto CPP_ARG_REMOVED_PREFIX = "removed_cppArg"_L1;
+
+QString CPP_ARG_REMOVED(int i)
+{
+ return CPP_ARG_REMOVED_PREFIX + QString::number(i);
+}
+
+const char *const METHOD_DEF_SENTINEL = "{nullptr, nullptr, 0, nullptr} // Sentinel\n";
+const char *const PYTHON_TO_CPPCONVERSION_STRUCT = "Shiboken::Conversions::PythonToCppConversion";
+
+const char *const openTargetExternC = R"(
+// Target ---------------------------------------------------------
+
+extern "C" {
+)";
+const char *const closeExternC = "} // extern \"C\"\n\n";
+const char *const richCompareComment =
+ "// PYSIDE-74: By default, we redirect to object's tp_richcompare (which is `==`, `!=`).\n";
+
+struct ShibokenGeneratorOptions
+{
+ bool useCtorHeuristic = false;
+ bool userReturnValueHeuristic = false;
+ bool verboseErrorMessagesDisabled = false;
+ bool useIsNullAsNbBool = false;
+ // FIXME PYSIDE 7 Flip m_leanHeaders default or remove?
+ bool leanHeaders = false;
+ bool useOperatorBoolAsNbBool = false;
+ // FIXME PYSIDE 7 Flip generateImplicitConversions default or remove?
+ bool generateImplicitConversions = true;
+ bool wrapperDiagnostics = false;
+};
struct GeneratorClassInfoCacheEntry
{
ShibokenGenerator::FunctionGroups functionGroups;
+ QList<AbstractMetaFunctionCList> numberProtocolOperators;
+ BoolCastFunctionOptional boolCastFunctionO;
bool needsGetattroFunction = false;
};
-using GeneratorClassInfoCache = QHash<const AbstractMetaClass *, GeneratorClassInfoCacheEntry>;
+using GeneratorClassInfoCache = QHash<AbstractMetaClassCPtr, GeneratorClassInfoCacheEntry>;
Q_GLOBAL_STATIC(GeneratorClassInfoCache, generatorClassInfoCache)
@@ -97,6 +134,10 @@ const ShibokenGenerator::TypeSystemConverterRegExps &
return result;
}
+// Options are static to avoid duplicated handling since ShibokenGenerator
+// is instantiated for HeaderGenerator and CppGenerator.
+ShibokenGeneratorOptions ShibokenGenerator::m_options;
+
ShibokenGenerator::ShibokenGenerator() = default;
ShibokenGenerator::~ShibokenGenerator() = default;
@@ -105,32 +146,32 @@ ShibokenGenerator::~ShibokenGenerator() = default;
static const QHash<QString, QString> &primitiveTypesCorrespondences()
{
static const QHash<QString, QString> result = {
- {u"bool"_s, pyBoolT()},
- {u"char"_s, sbkCharT()},
- {u"signed char"_s, sbkCharT()},
- {u"unsigned char"_s, sbkCharT()},
- {intT(), pyIntT()},
- {u"signed int"_s, pyIntT()},
- {u"uint"_s, pyIntT()},
- {u"unsigned int"_s, pyIntT()},
- {shortT(), pyIntT()},
- {u"ushort"_s, pyIntT()},
- {u"signed short"_s, pyIntT()},
- {u"signed short int"_s, pyIntT()},
- {unsignedShortT(), pyIntT()},
- {u"unsigned short int"_s, pyIntT()},
- {longT(), pyIntT()},
- {doubleT(), pyFloatT()},
- {floatT(), pyFloatT()},
- {u"unsigned long"_s, pyLongT()},
- {u"signed long"_s, pyLongT()},
- {u"ulong"_s, pyLongT()},
- {u"unsigned long int"_s, pyLongT()},
- {u"long long"_s, pyLongT()},
- {u"__int64"_s, pyLongT()},
- {u"unsigned long long"_s, pyLongT()},
- {u"unsigned __int64"_s, pyLongT()},
- {u"size_t"_s, pyLongT()}
+ {u"bool"_s, pyBoolT},
+ {u"char"_s, sbkCharT},
+ {u"signed char"_s, sbkCharT},
+ {u"unsigned char"_s, sbkCharT},
+ {intT, pyLongT},
+ {u"signed int"_s, pyLongT},
+ {u"uint"_s, pyLongT},
+ {u"unsigned int"_s, pyLongT},
+ {shortT, pyLongT},
+ {u"ushort"_s, pyLongT},
+ {u"signed short"_s, pyLongT},
+ {u"signed short int"_s, pyLongT},
+ {unsignedShortT, pyLongT},
+ {u"unsigned short int"_s, pyLongT},
+ {longT, pyLongT},
+ {doubleT, pyFloatT},
+ {floatT, pyFloatT},
+ {u"unsigned long"_s, pyLongT},
+ {u"signed long"_s, pyLongT},
+ {u"ulong"_s, pyLongT},
+ {u"unsigned long int"_s, pyLongT},
+ {u"long long"_s, pyLongT},
+ {u"__int64"_s, pyLongT},
+ {u"unsigned long long"_s, pyLongT},
+ {u"unsigned __int64"_s, pyLongT},
+ {u"size_t"_s, pyLongT}
};
return result;
}
@@ -140,24 +181,24 @@ const QHash<QString, QChar> &ShibokenGenerator::formatUnits()
static const QHash<QString, QChar> result = {
{u"char"_s, u'b'},
{u"unsigned char"_s, u'B'},
- {intT(), u'i'},
+ {intT, u'i'},
{u"unsigned int"_s, u'I'},
- {shortT(), u'h'},
- {unsignedShortT(), u'H'},
- {longT(), u'l'},
- {unsignedLongLongT(), u'k'},
- {longLongT(), u'L'},
+ {shortT, u'h'},
+ {unsignedShortT, u'H'},
+ {longT, u'l'},
+ {unsignedLongLongT, u'k'},
+ {longLongT, u'L'},
{u"__int64"_s, u'L'},
- {unsignedLongLongT(), u'K'},
+ {unsignedLongLongT, u'K'},
{u"unsigned __int64"_s, u'K'},
- {doubleT(), u'd'},
- {floatT(), u'f'},
+ {doubleT, u'd'},
+ {floatT, u'f'},
};
return result;
}
QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType &cType,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
Options options) const
{
if (cType.isArray()) {
@@ -174,7 +215,7 @@ QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType
return translateType(cType, context, options);
}
-bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaClass) const
+bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClassCPtr &metaClass)
{
const auto wrapper = metaClass->cppWrapper();
return wrapper.testFlag(AbstractMetaClass::CppVirtualMethodWrapper)
@@ -182,8 +223,17 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaCl
&& wrapper.testFlag(AbstractMetaClass::CppProtectedHackWrapper));
}
-ShibokenGenerator::FunctionGeneration
- ShibokenGenerator::functionGeneration(const AbstractMetaFunctionCPtr &func) const
+bool ShibokenGenerator::shouldGenerateMetaObjectFunctions(const AbstractMetaClassCPtr &metaClass)
+{
+ return usePySideExtensions()
+ && (!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
+ && !metaClass->typeEntry()->typeFlags()
+ .testFlag(ComplexTypeEntry::DisableQtMetaObjectFunctions)
+ && isQObject(metaClass);
+}
+
+ShibokenGenerator::FunctionGeneration ShibokenGenerator::functionGeneration(
+ const AbstractMetaFunctionCPtr &func)
{
FunctionGeneration result;
@@ -226,14 +276,15 @@ ShibokenGenerator::FunctionGeneration
// Check on virtuals (including operators).
const bool isAbstract = func->isAbstract();
if (!(isAbstract || func->isVirtual())
- || func->attributes().testFlag(AbstractMetaFunction::FinalCppMethod)) {
+ || func->cppAttributes().testFlag(FunctionAttribute::Final)
+ || func->isModifiedFinal()) {
return result;
}
// MetaObject virtuals only need to be declared; CppGenerator creates a
// special implementation.
if (functionType == AbstractMetaFunction::NormalFunction
- && usePySideExtensions() && func->ownerClass()->isQObject()) {
+ && usePySideExtensions() && isQObject(func->ownerClass())) {
const QString &name = func->name();
if (name == u"metaObject"_s || name == u"qt_metacall") {
result.setFlag(FunctionGenerationFlag::QMetaObjectMethod);
@@ -248,11 +299,12 @@ ShibokenGenerator::FunctionGeneration
return result;
}
-AbstractMetaFunctionCList ShibokenGenerator::implicitConversions(const TypeEntry *t) const
+AbstractMetaFunctionCList ShibokenGenerator::implicitConversions(const TypeEntryCPtr &t) const
{
- if (!generateImplicitConversions())
+ if (!generateImplicitConversions() || !t->isValue())
return {};
- auto *customConversion = t->customConversion();
+ auto vte = std::static_pointer_cast<const ValueTypeEntry>(t);
+ auto customConversion = vte->customConversion();
if (customConversion && customConversion->replaceOriginalTargetToNativeConversions())
return {};
@@ -265,7 +317,7 @@ AbstractMetaFunctionCList ShibokenGenerator::implicitConversions(const TypeEntry
return result;
}
-QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const
+QString ShibokenGenerator::wrapperName(const AbstractMetaClassCPtr &metaClass)
{
Q_ASSERT(shouldGenerateCppWrapper(metaClass));
QString result = metaClass->name();
@@ -274,19 +326,55 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const
return result + u"Wrapper"_s;
}
-QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClassCPtr &metaClass)
{
QString fullClassName = metaClass->name();
- const AbstractMetaClass *enclosing = metaClass->enclosingClass();
+ auto enclosing = metaClass->enclosingClass();
while (enclosing) {
if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry()))
fullClassName.prepend(enclosing->name() + u'.');
enclosing = enclosing->enclosingClass();
}
- fullClassName.prepend(packageName() + u'.');
+ fullClassName.prepend(metaClass->typeEntry()->targetLangPackage() + u'.');
return fullClassName;
}
+QString ShibokenGenerator::headerFileNameForContext(const GeneratorContext &context)
+{
+ return fileNameForContextHelper(context, u"_wrapper.h"_s);
+}
+
+// PYSIDE-500: When avoiding the protected hack, also include the inherited
+// wrapper classes of the *current* module, because without the protected hack,
+// we sometimes need to cast inherited wrappers. Inherited classes
+// of *other* modules are completely regenerated by the header generator
+// since the wrapper headers are not installed.
+
+IncludeGroup ShibokenGenerator::baseWrapperIncludes(const GeneratorContext &classContext) const
+{
+ IncludeGroup result{u"Wrappers"_s, {}};
+ if (!classContext.useWrapper() || !avoidProtectedHack()
+ || classContext.forSmartPointer()) {
+ return result;
+ }
+
+ const auto moduleEntry = TypeDatabase::instance()->defaultTypeSystemType();
+ const auto &baseClasses = allBaseClasses(classContext.metaClass());
+ for (const auto &base : baseClasses) {
+ const auto te = base->typeEntry();
+ if (te->codeGeneration() == TypeEntry::GenerateCode) { // current module
+ const auto context = contextForClass(base);
+ if (context.useWrapper()) {
+ const QString header = headerFileNameForContext(context);
+ const auto type = typeSystemTypeEntry(te) == moduleEntry
+ ? Include::LocalPath : Include::IncludePath;
+ result.append(Include(type, header));
+ }
+ }
+ }
+ return result;
+}
+
QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunctionCPtr &func, bool forceFunc)
{
QString funcName;
@@ -311,6 +399,11 @@ QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunctionCPtr
return funcName;
}
+bool ShibokenGenerator::wrapperDiagnostics()
+{
+ return m_options.wrapperDiagnostics;
+}
+
QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum &metaEnum)
{
QString result = metaEnum.fullName();
@@ -346,37 +439,37 @@ QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunctionCPtr &f
QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunctionCPtr &func)
{
if (!func->ownerClass())
- return QString();
+ return {};
return cpythonBaseName(func->ownerClass()->typeEntry()) + u"Method_"_s
+ func->name();
}
-QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass) + u"_getsetlist"_s;
}
-QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass) + u"_setattro"_s;
}
-QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass) + u"_getattro"_s;
}
QString ShibokenGenerator::cpythonGetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass)
+ const AbstractMetaClassCPtr &enclosingClass)
{
- return cpythonBaseName(enclosingClass) + QStringLiteral("_get_") + name;
+ return cpythonBaseName(enclosingClass) + "_get_"_L1 + name;
}
QString ShibokenGenerator::cpythonSetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass)
+ const AbstractMetaClassCPtr &enclosingClass)
{
- return cpythonBaseName(enclosingClass) + QStringLiteral("_set_") + name;
+ return cpythonBaseName(enclosingClass) + "_set_"_L1 + name;
}
QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField &metaField)
@@ -390,13 +483,13 @@ QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField &me
}
QString ShibokenGenerator::cpythonGetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
return cpythonGetterFunctionName(property.name(), metaClass);
}
QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass)
+ const AbstractMetaClassCPtr &metaClass)
{
return cpythonSetterFunctionName(property.name(), metaClass);
}
@@ -409,7 +502,7 @@ static QString cpythonEnumFlagsName(const QString &moduleName,
return result;
}
-QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry *enumEntry)
+QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntryCPtr &enumEntry)
{
QString p = enumEntry->targetLangPackage();
p.replace(u'.', u'_');
@@ -421,7 +514,7 @@ QString ShibokenGenerator::cpythonEnumName(const AbstractMetaEnum &metaEnum)
return cpythonEnumName(metaEnum.typeEntry());
}
-QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry *flagsEntry)
+QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntryCPtr &flagsEntry)
{
QString p = flagsEntry->targetLangPackage();
p.replace(u'.', u'_');
@@ -430,18 +523,16 @@ QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry *flagsEntry)
QString ShibokenGenerator::cpythonFlagsName(const AbstractMetaEnum *metaEnum)
{
- const FlagsTypeEntry *flags = metaEnum->typeEntry()->flags();
- if (!flags)
- return QString();
- return cpythonFlagsName(flags);
+ const auto flags = metaEnum->typeEntry()->flags();
+ return flags ? cpythonFlagsName(flags) : QString{};
}
-QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass->typeEntry()) + u"SpecialCastFunction"_s;
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass *metaClass,
+QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClassCPtr &metaClass,
const QString &argName)
{
return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
@@ -451,40 +542,41 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType &metaType,
const QString &argName)
{
if (!metaType.isWrapperType())
- return QString();
+ return {};
return u"reinterpret_cast< ::"_s + metaType.cppSignature()
+ u" *>(Shiboken::Conversions::cppPointer("_s + cpythonTypeNameExt(metaType)
+ u", reinterpret_cast<SbkObject *>("_s + argName + u")))"_s;
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry *type,
+QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntryCPtr &type,
const QString &argName)
{
if (!type->isWrapperType())
return QString();
- return u"reinterpret_cast< ::"_s + type->qualifiedCppName()
+ return u"reinterpret_cast< "_s + getFullTypeName(type)
+ u" *>(Shiboken::Conversions::cppPointer("_s + cpythonTypeNameExt(type)
+ u", reinterpret_cast<SbkObject *>("_s + argName + u")))"_s;
}
void ShibokenGenerator::writeToPythonConversion(TextStream & s, const AbstractMetaType &type,
- const AbstractMetaClass * /* context */,
+ const AbstractMetaClassCPtr & /* context */,
const QString &argumentName)
{
s << cpythonToPythonConversionFunction(type) << argumentName << ')';
}
-void ShibokenGenerator::writeToCppConversion(TextStream &s, const AbstractMetaClass *metaClass,
+void ShibokenGenerator::writeToCppConversion(TextStream &s,
+ const AbstractMetaClassCPtr &metaClass,
const QString &inArgName, const QString &outArgName)
{
s << cpythonToCppConversionFunction(metaClass) << inArgName << ", &" << outArgName << ')';
}
void ShibokenGenerator::writeToCppConversion(TextStream &s, const AbstractMetaType &type,
- const AbstractMetaClass *context, const QString &inArgName,
+ const QString &inArgName,
const QString &outArgName)
{
- s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')';
+ s << cpythonToCppConversionFunction(type) << inArgName << ", &" << outArgName << ')';
}
bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunctionCPtr &func,
@@ -519,66 +611,61 @@ QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType &type)
return cpythonBaseName(type.typeEntry());
}
-QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonBaseName(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonBaseName(const TypeEntry *type)
+QString ShibokenGenerator::containerCpythonBaseName(const ContainerTypeEntryCPtr &ctype)
+{
+ switch (ctype->containerKind()) {
+ case ContainerTypeEntry::SetContainer:
+ return u"PySet"_s;
+ case ContainerTypeEntry::MapContainer:
+ case ContainerTypeEntry::MultiMapContainer:
+ return u"PyDict"_s;
+ case ContainerTypeEntry::ListContainer:
+ case ContainerTypeEntry::PairContainer:
+ case ContainerTypeEntry::SpanContainer:
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ return cPySequenceT;
+}
+
+QString ShibokenGenerator::cpythonBaseName(const TypeEntryCPtr &type)
{
QString baseName;
if (type->isWrapperType() || type->isNamespace()) { // && type->referenceType() == NoReference) {
baseName = u"Sbk_"_s + type->name();
} else if (type->isPrimitive()) {
- const auto *ptype = type->asPrimitive()->basicReferencedTypeEntry();
+ const auto ptype = basicReferencedTypeEntry(type);
baseName = ptype->hasTargetLangApiType()
? ptype->targetLangApiName() : pythonPrimitiveTypeName(ptype->name());
} else if (type->isEnum()) {
- baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type));
+ baseName = cpythonEnumName(std::static_pointer_cast<const EnumTypeEntry>(type));
} else if (type->isFlags()) {
- baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type));
+ baseName = cpythonFlagsName(std::static_pointer_cast<const FlagsTypeEntry>(type));
} else if (type->isContainer()) {
- const auto *ctype = static_cast<const ContainerTypeEntry *>(type);
- switch (ctype->containerKind()) {
- case ContainerTypeEntry::ListContainer:
- //baseName = "PyList";
- //break;
- case ContainerTypeEntry::PairContainer:
- //baseName = "PyTuple";
- baseName = cPySequenceT();
- break;
- case ContainerTypeEntry::SetContainer:
- baseName = u"PySet"_s;
- break;
- case ContainerTypeEntry::MapContainer:
- case ContainerTypeEntry::MultiMapContainer:
- baseName = u"PyDict"_s;
- break;
- default:
- Q_ASSERT(false);
- }
+ const auto ctype = std::static_pointer_cast<const ContainerTypeEntry>(type);
+ baseName = containerCpythonBaseName(ctype);
} else {
- baseName = cPyObjectT();
+ baseName = cPyObjectT;
}
return baseName.replace(u"::"_s, u"_"_s);
}
-QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClassCPtr &metaClass)
{
return cpythonTypeName(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonTypeName(const TypeEntry *type)
+QString ShibokenGenerator::cpythonTypeName(const TypeEntryCPtr &type)
{
return cpythonBaseName(type) + u"_TypeF()"_s;
}
-QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry *type)
-{
- return cppApiVariableName(type->targetLangPackage()) + u'['
- + getTypeIndexVariableName(type) + u']';
-}
-
QString ShibokenGenerator::converterObject(const AbstractMetaType &type)
{
if (type.isCString())
@@ -587,7 +674,7 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType &type)
return u"Shiboken::Conversions::PrimitiveTypeConverter<void *>()"_s;
const AbstractMetaTypeList nestedArrayTypes = type.nestedArrayTypes();
if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast().isCppPrimitive()) {
- return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<")
+ return "Shiboken::Conversions::ArrayTypeConverter<"_L1
+ nestedArrayTypes.constLast().minimalSignature()
+ u">("_s + QString::number(nestedArrayTypes.size())
+ u')';
@@ -601,34 +688,31 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType &type)
return converterObject(typeEntry);
}
-QString ShibokenGenerator::converterObject(const TypeEntry *type)
+QString ShibokenGenerator::converterObject(const TypeEntryCPtr &type)
{
- if (type->isExtendedCppPrimitive())
+ if (isExtendedCppPrimitive(type))
return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()")
.arg(type->qualifiedCppName());
if (type->isWrapperType())
return QString::fromLatin1("PepType_SOTP(reinterpret_cast<PyTypeObject *>(%1))->converter")
.arg(cpythonTypeNameExt(type));
- if (type->isEnum())
+ if (type->isEnum() || type->isFlags())
return QString::fromLatin1("PepType_SETP(reinterpret_cast<SbkEnumType *>(%1))->converter")
.arg(cpythonTypeNameExt(type));
- if (type->isFlags())
- return QString::fromLatin1("PepType_PFTP(reinterpret_cast<PySideQFlagsType *>(%1))->converter")
- .arg(cpythonTypeNameExt(type));
if (type->isArray()) {
qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName();
- return QString();
+ return {};
}
/* the typedef'd primitive types case */
- const auto *pte = dynamic_cast<const PrimitiveTypeEntry *>(type);
+ auto pte = std::dynamic_pointer_cast<const PrimitiveTypeEntry>(type);
if (!pte) {
qDebug() << "Warning: the Qt5 primitive type is unknown" << type->qualifiedCppName();
- return QString();
+ return {};
}
- pte = pte->basicReferencedTypeEntry();
- if (pte->isPrimitive() && !pte->isCppPrimitive() && !pte->customConversion()) {
+ pte = basicReferencedTypeEntry(pte);
+ if (pte->isPrimitive() && !isCppPrimitive(pte) && !pte->customConversion()) {
return u"Shiboken::Conversions::PrimitiveTypeConverter<"_s
+ pte->qualifiedCppName() + u">()"_s;
}
@@ -637,19 +721,35 @@ QString ShibokenGenerator::converterObject(const TypeEntry *type)
+ u'[' + getTypeIndexVariableName(type) + u']';
}
-QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType &type)
+QString ShibokenGenerator::cpythonTypeNameExtSet(const TypeEntryCPtr &type)
+{
+ return cppApiVariableName(type->targetLangPackage()) + u'['
+ + getTypeIndexVariableName(type) + "].type"_L1;
+}
+
+QString ShibokenGenerator::cpythonTypeNameExtSet(const AbstractMetaType &type)
{
return cppApiVariableName(type.typeEntry()->targetLangPackage()) + u'['
- + getTypeIndexVariableName(type) + u']';
+ + getTypeIndexVariableName(type) + "].type"_L1;
}
-static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); }
+QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntryCPtr &type)
+{
+ return "Shiboken::Module::get("_L1 + cppApiVariableName(type->targetLangPackage())
+ + u'[' + getTypeIndexVariableName(type) + "])"_L1;
+}
-QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion *toNative)
+QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType &type)
{
- if (toNative->sourceType())
- return fixedCppTypeName(toNative->sourceType());
- return toNative->sourceTypeName();
+ return u"Shiboken::Module::get("_s + cppApiVariableName(type.typeEntry()->targetLangPackage())
+ + u'[' + getTypeIndexVariableName(type) + "])"_L1;
+}
+
+QString ShibokenGenerator::fixedCppTypeName(const TargetToNativeConversion &toNative)
+{
+ if (toNative.sourceType())
+ return fixedCppTypeName(toNative.sourceType());
+ return toNative.sourceTypeName();
}
QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType &type)
{
@@ -668,7 +768,7 @@ static QString _fixedCppTypeName(QString typeName)
typeName.replace(u"&"_s, u"REF"_s);
return typeName;
}
-QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeName)
+QString ShibokenGenerator::fixedCppTypeName(const TypeEntryCPtr &type, QString typeName)
{
if (typeName.isEmpty())
typeName = type->qualifiedCppName();
@@ -692,8 +792,8 @@ QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction
{
QString op = Generator::pythonOperatorFunctionName(func->originalName());
if (op.isEmpty()) {
- qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func.data());
- return unknownOperator();
+ qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func.get());
+ return "__UNKNOWN_OPERATOR__"_L1;
}
if (func->arguments().isEmpty()) {
if (op == u"__sub__")
@@ -710,27 +810,26 @@ QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction
bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
{
- return cpythonApiName == pyIntT()
- || cpythonApiName == pyFloatT() || cpythonApiName == pyLongT()
- || cpythonApiName == pyBoolT();
+ return cpythonApiName == pyFloatT || cpythonApiName == pyLongT
+ || cpythonApiName == pyBoolT;
}
static std::optional<TypeSystem::CPythonType>
- targetLangApiCPythonType(const PrimitiveTypeEntry *t)
+ targetLangApiCPythonType(const PrimitiveTypeEntryCPtr &t)
{
if (!t->hasTargetLangApiType())
return {};
- const auto *cte = t->targetLangApiType();
+ const auto cte = t->targetLangApiType();
if (cte->type() != TypeEntry::PythonType)
return {};
- return static_cast<const PythonTypeEntry *>(cte)->cPythonType();
+ return std::static_pointer_cast<const PythonTypeEntry>(cte)->cPythonType();
}
-bool ShibokenGenerator::isNumber(const TypeEntry *type)
+bool ShibokenGenerator::isNumber(const TypeEntryCPtr &type)
{
if (!type->isPrimitive())
return false;
- const auto *pte = type->asPrimitive()->basicReferencedTypeEntry();
+ const auto pte = basicReferencedTypeEntry(type);
const auto cPythonTypeOpt = targetLangApiCPythonType(pte);
// FIXME PYSIDE-1660: Return false here after making primitive types built-in?
if (!cPythonTypeOpt.has_value()) {
@@ -749,17 +848,17 @@ bool ShibokenGenerator::isNumber(const AbstractMetaType &type)
return isNumber(type.typeEntry());
}
-bool ShibokenGenerator::isPyInt(const TypeEntry *type)
+bool ShibokenGenerator::isPyInt(const TypeEntryCPtr &type)
{
if (!type->isPrimitive())
return false;
- const auto *pte = type->asPrimitive()->basicReferencedTypeEntry();
+ const auto pte = basicReferencedTypeEntry(type);
const auto cPythonTypeOpt = targetLangApiCPythonType(pte);
// FIXME PYSIDE-1660: Return false here after making primitive types built-in?
if (!cPythonTypeOpt.has_value()) {
const auto &mapping = primitiveTypesCorrespondences();
const auto it = mapping.constFind(pte->name());
- return it != mapping.cend() && it.value() == pyLongT();
+ return it != mapping.cend() && it.value() == pyLongT;
}
return cPythonTypeOpt.value() == TypeSystem::CPythonType::Integer;
}
@@ -777,9 +876,9 @@ bool ShibokenGenerator::isNullPtr(const QString &value)
QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType)
{
- const auto *typeEntry = metaType.typeEntry();
+ const auto typeEntry = metaType.typeEntry();
if (typeEntry->isCustom()) {
- const auto *cte = static_cast<const CustomTypeEntry *>(typeEntry);
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(typeEntry);
if (cte->hasCheckFunction())
return cte->checkFunction();
throw Exception(msgUnknownCheckFunction(typeEntry));
@@ -796,7 +895,7 @@ QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType)
if (typeEntry->isContainer()) {
QString typeCheck = u"Shiboken::Conversions::"_s;
ContainerTypeEntry::ContainerKind type =
- static_cast<const ContainerTypeEntry *>(typeEntry)->containerKind();
+ std::static_pointer_cast<const ContainerTypeEntry>(typeEntry)->containerKind();
if (type == ContainerTypeEntry::ListContainer
|| type == ContainerTypeEntry::SetContainer) {
const QString containerType = type == ContainerTypeEntry::SetContainer
@@ -844,10 +943,10 @@ QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType)
return cpythonCheckFunction(typeEntry);
}
-QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type)
+QString ShibokenGenerator::cpythonCheckFunction(TypeEntryCPtr type)
{
if (type->isCustom()) {
- const auto *cte = static_cast<const CustomTypeEntry *>(type);
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(type);
if (cte->hasCheckFunction())
return cte->checkFunction();
throw Exception(msgUnknownCheckFunction(type));
@@ -857,28 +956,26 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type)
return u"SbkObject_TypeCheck("_s + cpythonTypeNameExt(type) + u", "_s;
if (type->isPrimitive())
- type = type->asPrimitive()->basicReferencedTypeEntry();
+ type = basicReferencedTypeEntry(type);
- if (auto *tla = type->targetLangApiType()) {
+ if (auto tla = type->targetLangApiType()) {
if (tla->hasCheckFunction())
return tla->checkFunction();
}
- if (type->isExtendedCppPrimitive()) {
- const auto *pte = type->asPrimitive();
- return pythonPrimitiveTypeName(pte->name()) + u"_Check"_s;
- }
+ if (isExtendedCppPrimitive(type))
+ return pythonPrimitiveTypeName(type->name()) + u"_Check"_s;
return cpythonIsConvertibleFunction(type);
}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry *type)
+QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntryCPtr &type)
{
if (type->isWrapperType()) {
QString result = u"Shiboken::Conversions::"_s;
bool isValue = false;
if (type->isValue()) {
- const auto *cte = static_cast<const ComplexTypeEntry *>(type);
+ const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(type);
isValue = !cte->isValueTypeWithCopyConstructorOnly();
}
result += isValue ? u"isPythonToCppValueConvertible"_s
@@ -890,11 +987,11 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry *type)
.arg(converterObject(type));
}
-QString ShibokenGenerator::cpythonIsConvertibleFunction(AbstractMetaType metaType)
+QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType &metaType)
{
- const auto *typeEntry = metaType.typeEntry();
+ const auto typeEntry = metaType.typeEntry();
if (typeEntry->isCustom()) {
- const auto *cte = static_cast<const CustomTypeEntry *>(typeEntry);
+ const auto cte = std::static_pointer_cast<const CustomTypeEntry>(typeEntry);
if (cte->hasCheckFunction())
return cte->checkFunction();
throw Exception(msgUnknownCheckFunction(typeEntry));
@@ -907,12 +1004,14 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(AbstractMetaType metaTyp
return result;
}
if (metaType.isWrapperType()) {
- if (metaType.isPointer() || metaType.isValueTypeWithCopyConstructorOnly())
+ if (metaType.isPointer() || metaType.isValueTypeWithCopyConstructorOnly()) {
result += u"pythonToCppPointerConversion"_s;
- else if (metaType.referenceType() == LValueReference)
+ } else if (metaType.referenceType() == LValueReference
+ || (metaType.referenceType() == RValueReference && typeEntry->isObject())) {
result += u"pythonToCppReferenceConversion"_s;
- else
+ } else {
result += u"pythonToCppValueConversion"_s;
+ }
result += u'(' + cpythonTypeNameExt(metaType) + u", "_s;
return result;
}
@@ -935,26 +1034,24 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgume
return cpythonIsConvertibleFunction(metaArg.type());
}
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClassCPtr &metaClass)
{
return u"Shiboken::Conversions::pythonToCppPointer("_s
+ cpythonTypeNameExt(metaClass->typeEntry()) + u", "_s;
}
-QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass * /* context */)
+QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType &type)
{
if (type.isWrapperType()) {
return u"Shiboken::Conversions::pythonToCpp"_s
+ (type.isPointer() ? u"Pointer"_s : u"Copy"_s)
+ u'(' + cpythonTypeNameExt(type) + u", "_s;
}
- return QStringLiteral("Shiboken::Conversions::pythonToCppCopy(%1, ")
- .arg(converterObject(type));
+ return "Shiboken::Conversions::pythonToCppCopy("_L1
+ + converterObject(type) + ", "_L1;
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass * /* context */)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType &type)
{
if (type.isWrapperType()) {
QString conversion;
@@ -973,17 +1070,18 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaT
result += u'&';
return result;
}
- return QStringLiteral("Shiboken::Conversions::copyToPython(%1, %2")
- .arg(converterObject(type),
- (type.isCString() || type.isVoidPointer()) ? QString() : u"&"_s);
+
+ const auto indirections = type.indirections() - 1;
+ return u"Shiboken::Conversions::copyToPython("_s + converterObject(type)
+ + u", "_s + AbstractMetaType::dereferencePrefix(indirections);
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClassCPtr &metaClass)
{
return cpythonToPythonConversionFunction(metaClass->typeEntry());
}
-QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry *type)
+QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntryCPtr &type)
{
if (type->isWrapperType()) {
const QString conversion = type->isValue() ? u"copy"_s : u"pointer"_s;
@@ -1006,13 +1104,14 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunctionCPtr &func,
auto type = options.testFlag(OriginalTypeDescription)
? argument.type() : argument.modifiedType();
+
QString arg = translateType(type, func->implementingClass(), options);
if (argument.isTypeModified())
arg.replace(u'$', u'.'); // Haehh?
// "int a", "int a[]"
- const int arrayPos = arg.indexOf(u'[');
+ const auto arrayPos = arg.indexOf(u'[');
if (arrayPos != -1)
arg.insert(arrayPos, u' ' + argument.name());
else
@@ -1047,11 +1146,12 @@ void ShibokenGenerator::writeFunctionArguments(TextStream &s,
const AbstractMetaFunctionCPtr &func,
Options options) const
{
- AbstractMetaArgumentList arguments = func->arguments();
-
int argUsed = 0;
- for (int i = 0; i < arguments.size(); ++i) {
- const auto &arg = arguments.at(i);
+ if (func->isUserAddedPythonOverride()) {
+ s << "Shiboken::GilState &gil, PyObject *" << PYTHON_OVERRIDE_VAR;
+ argUsed += 2;
+ }
+ for (const auto &arg : func->arguments()) {
if (options.testFlag(Generator::SkipRemovedArguments) && arg.isModifiedRemoved())
continue;
@@ -1062,7 +1162,7 @@ void ShibokenGenerator::writeFunctionArguments(TextStream &s,
}
}
-GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) const
+GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClassCPtr &c) const
{
GeneratorContext result = Generator::contextForClass(c);
if (shouldGenerateCppWrapper(c)) {
@@ -1087,6 +1187,8 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunctionCPtr &fun
{
StringStream s(TextStream::Language::Cpp);
// The actual function
+ if (!options.testFlag(Option::SkipDefaultValues) && func->isStatic()) // Declaration
+ s << "static ";
if (func->isEmptyFunction() || func->needsReturnType())
s << functionReturnType(func, options) << ' ';
else
@@ -1148,15 +1250,10 @@ void ShibokenGenerator::writeFunctionCall(TextStream &s,
s << ')';
}
-void ShibokenGenerator::writeUnusedVariableCast(TextStream &s, const QString &variableName)
-{
- s << "SBK_UNUSED(" << variableName<< ")\n";
-}
-
ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const
{
ExtendedConverterData extConvs;
- for (auto metaClass : api().classes()) {
+ for (const auto &metaClass : api().classes()) {
// Use only the classes for the current module.
if (!shouldGenerate(metaClass->typeEntry()))
continue;
@@ -1164,7 +1261,7 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter
for (const auto &convOp : overloads) {
// Get only the conversion operators that return a type from another module,
// that are value-types and were not removed in the type system.
- const TypeEntry *convType = convOp->type().typeEntry();
+ const auto convType = convOp->type().typeEntry();
if (convType->generateCode() || !convType->isValue()
|| convOp->isModifiedRemoved())
continue;
@@ -1174,15 +1271,13 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter
return extConvs;
}
-QList<const CustomConversion *> ShibokenGenerator::getPrimitiveCustomConversions()
+QList<CustomConversionPtr> ShibokenGenerator::getPrimitiveCustomConversions()
{
- QList<const CustomConversion *> conversions;
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *type : primitiveTypeList) {
- if (!type->shouldGenerate() || !type->isUserPrimitive() || !type->customConversion())
- continue;
-
- conversions << type->customConversion();
+ QList<CustomConversionPtr> conversions;
+ const auto &primitiveTypeList = primitiveTypes();
+ for (const auto &type : primitiveTypeList) {
+ if (type->shouldGenerate() && isUserPrimitive(type) && type->hasCustomConversion())
+ conversions << type->customConversion();
}
return conversions;
}
@@ -1195,7 +1290,7 @@ static QString getArgumentsFromMethodCall(const QString &str)
// For more information check this:
// http://perl.plover.com/yak/regex/samples/slide083.html
static QLatin1String funcCall("%CPPSELF.%FUNCTION_NAME");
- int pos = str.indexOf(funcCall);
+ auto pos = str.indexOf(funcCall);
if (pos == -1)
return QString();
pos = pos + funcCall.size();
@@ -1239,7 +1334,7 @@ void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorConte
code.replace(u"%TYPE"_s, className);
code.replace(u"%CPPTYPE"_s, metaClass->name());
- processCodeSnip(code);
+ processCodeSnip(code, context.effectiveClassName());
}
void ShibokenGenerator::processCodeSnip(QString &code) const
@@ -1257,6 +1352,15 @@ void ShibokenGenerator::processCodeSnip(QString &code) const
replaceTypeCheckTypeSystemVariable(code);
}
+void ShibokenGenerator::processCodeSnip(QString &code, const QString &context) const
+{
+ try {
+ processCodeSnip(code);
+ } catch (const std::exception &e) {
+ throw Exception(msgSnippetError(context, e.what()));
+ }
+}
+
ShibokenGenerator::ArgumentVarReplacementList
ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunctionCPtr &func,
bool usePyArgs, TypeSystem::Language language,
@@ -1266,7 +1370,7 @@ ShibokenGenerator::ArgumentVarReplacementList
TypeSystem::Language convLang = (language == TypeSystem::TargetLangCode)
? TypeSystem::NativeCode : TypeSystem::TargetLangCode;
int removed = 0;
- for (int i = 0; i < func->arguments().size(); ++i) {
+ for (qsizetype i = 0; i < func->arguments().size(); ++i) {
const AbstractMetaArgument &arg = func->arguments().at(i);
QString argValue;
if (language == TypeSystem::TargetLangCode) {
@@ -1277,7 +1381,7 @@ ShibokenGenerator::ArgumentVarReplacementList
if (argRemoved && hasConversionRule)
argValue = arg.name() + CONV_RULE_OUT_VAR_SUFFIX;
else if (argRemoved || (lastArg && arg.argumentIndex() > lastArg->argumentIndex()))
- argValue = CPP_ARG_REMOVED + QString::number(i);
+ argValue = CPP_ARG_REMOVED(i);
if (!argRemoved && argValue.isEmpty()) {
int argPos = i - removed;
AbstractMetaType type = arg.modifiedType();
@@ -1287,9 +1391,9 @@ ShibokenGenerator::ArgumentVarReplacementList
} else {
argValue = hasConversionRule
? arg.name() + CONV_RULE_OUT_VAR_SUFFIX
- : CPP_ARG + QString::number(argPos);
- auto deRef = type.shouldDereferenceArgument();
- AbstractMetaType::applyDereference(&argValue, deRef);
+ : CPP_ARG_N(argPos);
+ const auto generatorArg = GeneratorArgument::fromMetaType(type);
+ AbstractMetaType::applyDereference(&argValue, generatorArg.indirections);
}
}
} else {
@@ -1329,7 +1433,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
static void replacePyArg0(TypeSystem::Language language, QString *code)
{
- static const QString pyArg0 = u"%PYARG_0"_s;
+ static constexpr auto pyArg0 = "%PYARG_0"_L1;
if (!code->contains(pyArg0))
return;
@@ -1368,18 +1472,18 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// Replace %PYARG_# variables.
replacePyArg0(language, &code);
- static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)"));
+ static const QRegularExpression pyArgsRegex("%PYARG_(\\d+)"_L1);
Q_ASSERT(pyArgsRegex.isValid());
if (language == TypeSystem::TargetLangCode) {
if (usePyArgs) {
code.replace(pyArgsRegex, PYTHON_ARGS + u"[\\1-1]"_s);
} else {
- static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)"));
+ static const QRegularExpression pyArgsRegexCheck("%PYARG_([2-9]+)"_L1);
Q_ASSERT(pyArgsRegexCheck.isValid());
const QRegularExpressionMatch match = pyArgsRegexCheck.match(code);
if (match.hasMatch()) {
qCWarning(lcShiboken).noquote().nospace()
- << msgWrongIndex("%PYARG", match.captured(1), func.data());
+ << msgWrongIndex("%PYARG", match.captured(1), func.get());
return;
}
code.replace(u"%PYARG_1"_s, PYTHON_ARG);
@@ -1387,12 +1491,12 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
} else {
// Replaces the simplest case of attribution to a
// Python argument on the binding virtual method.
- static const QRegularExpression pyArgsAttributionRegex(QStringLiteral("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"));
+ static const QRegularExpression pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"_L1);
Q_ASSERT(pyArgsAttributionRegex.isValid());
code.replace(pyArgsAttributionRegex, u"PyTuple_SET_ITEM("_s
- + PYTHON_ARGS + u", \\1-1, \\2)"_s);
+ + PYTHON_ARGS + u".object(), \\1-1, \\2)"_s);
code.replace(pyArgsRegex, u"PyTuple_GET_ITEM("_s
- + PYTHON_ARGS + u", \\1-1)"_s);
+ + PYTHON_ARGS + u".object(), \\1-1)"_s);
}
// Replace %ARG#_TYPE variables.
@@ -1404,13 +1508,13 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
code.replace(argTypeVar, argTypeVal);
}
- static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE"));
+ static const QRegularExpression cppArgTypeRegexCheck("%ARG(\\d+)_TYPE"_L1);
Q_ASSERT(cppArgTypeRegexCheck.isValid());
QRegularExpressionMatchIterator rit = cppArgTypeRegexCheck.globalMatch(code);
while (rit.hasNext()) {
QRegularExpressionMatch match = rit.next();
qCWarning(lcShiboken).noquote().nospace()
- << msgWrongIndex("%ARG#_TYPE", match.captured(1), func.data());
+ << msgWrongIndex("%ARG#_TYPE", match.captured(1), func.get());
}
// Replace template variable for return variable name.
@@ -1496,7 +1600,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
QStringList args;
for (const ArgumentVarReplacementPair &pair : argReplacements) {
- if (pair.second.startsWith(CPP_ARG_REMOVED))
+ if (pair.second.startsWith(CPP_ARG_REMOVED_PREFIX))
continue;
args << pair.second;
}
@@ -1508,7 +1612,8 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
AbstractMetaType type = arg.modifiedType();
if (type.isWrapperType()) {
QString replacement = pair.second;
- if (type.shouldDereferenceArgument() > 0)
+ const auto generatorArg = GeneratorArgument::fromMetaType(type);
+ if (generatorArg.indirections > 0)
AbstractMetaType::stripDereference(&replacement);
if (type.referenceType() == LValueReference || type.isPointer())
code.replace(u'%' + QString::number(idx) + u'.', replacement + u"->"_s);
@@ -1545,8 +1650,8 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
if (isProtected) {
code.replace(u"%TYPE::%FUNCTION_NAME"_s,
- QStringLiteral("%1::%2_protected")
- .arg(wrapperName(func->ownerClass()), func->originalName()));
+ wrapperName(func->ownerClass()) + "::"_L1
+ + func->originalName() + "_protected"_L1);
code.replace(u"%FUNCTION_NAME"_s,
func->originalName() + u"_protected"_s);
}
@@ -1560,7 +1665,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
replaceTemplateVariables(code, func);
- processCodeSnip(code);
+ processCodeSnip(code, func->classQualifiedSignature());
s << "// Begin code injection\n" << code << "// End of code injection\n\n";
}
@@ -1568,7 +1673,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
// and false if it is a variable.
static bool isVariable(const QString &code)
{
- static const QRegularExpression expr(QStringLiteral("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$"));
+ static const QRegularExpression expr("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$"_L1);
Q_ASSERT(expr.isValid());
return expr.match(code.trimmed()).hasMatch();
}
@@ -1629,7 +1734,7 @@ const QHash<int, QString> &ShibokenGenerator::typeSystemConvName()
return result;
}
-using StringPair = QPair<QString, QString>;
+using StringPair = std::pair<QString, QString>;
void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable,
QString &code) const
@@ -1664,9 +1769,6 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
varType = miniNormalizer(varType);
QString varName = list.at(1).trimmed();
if (!varType.isEmpty()) {
- const QString conversionSignature = conversionType.cppSignature();
- if (varType != u"auto" && varType != conversionSignature)
- throw Exception(msgConversionTypesDiffer(varType, conversionSignature));
c << getFullTypeName(conversionType) << ' ' << varName
<< minimalConstructorExpression(api(), conversionType) << ";\n";
}
@@ -1683,7 +1785,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
case TypeSystemCheckFunction:
conversion = cpythonCheckFunction(conversionType);
if (conversionType.typeEntry()->isPrimitive()
- && (conversionType.typeEntry()->name() == cPyObjectT()
+ && (conversionType.typeEntry()->name() == cPyObjectT
|| !conversion.endsWith(u' '))) {
conversion += u'(';
break;
@@ -1714,9 +1816,9 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
}
}
}
- replacements.append(qMakePair(conversionString, conversion));
+ replacements.append(std::make_pair(conversionString, conversion));
}
- for (const StringPair &rep : qAsConst(replacements))
+ for (const StringPair &rep : std::as_const(replacements))
code.replace(rep.first, rep.second);
}
@@ -1741,12 +1843,13 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &con
return func->injectedCodeContains(wrappedCtorCall);
}
-bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClass *metaClass)
+bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClassCPtr &metaClass)
{
return metaClass->isPolymorphic();
}
-ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const AbstractMetaClass *metaClass) const
+ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(
+ const AbstractMetaClassCPtr &metaClass)
{
AttroCheck result;
if (metaClass->typeEntry()->isSmartPointer()) {
@@ -1758,7 +1861,7 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A
FunctionQueryOption::GetAttroFunction)) {
result |= AttroCheckFlag::GetattroUser;
}
- if (usePySideExtensions() && metaClass->qualifiedCppName() == qObjectT())
+ if (usePySideExtensions() && metaClass->qualifiedCppName() == qObjectT)
result |= AttroCheckFlag::SetattroQObject;
if (useOverrideCaching(metaClass))
result |= AttroCheckFlag::SetattroMethodOverride;
@@ -1770,14 +1873,14 @@ ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const A
// QObject, the property code needs to be generated, too.
if ((result & AttroCheckFlag::SetattroMask) != 0
&& !result.testFlag(AttroCheckFlag::SetattroQObject)
- && metaClass->isQObject()) {
+ && isQObject(metaClass)) {
result |= AttroCheckFlag::SetattroQObject;
}
}
return result;
}
-bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass)
+bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClassCPtr &metaClass)
{
if (!metaClass)
return false;
@@ -1786,7 +1889,7 @@ bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *
const auto &functionGroup = getFunctionGroups(metaClass);
for (auto it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
AbstractMetaFunctionCList overloads;
- for (const auto &func : qAsConst(it.value())) {
+ for (const auto &func : std::as_const(it.value())) {
if (func->isAssignmentOperator() || func->isConversionOperator()
|| func->isModifiedRemoved()
|| func->isPrivate() || func->ownerClass() != func->implementingClass()
@@ -1803,14 +1906,14 @@ bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *
}
AbstractMetaFunctionCList
- ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass *metaClass)
+ ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClassCPtr &metaClass)
{
AbstractMetaFunctionCList methods;
if (metaClass) {
const auto &functionGroups = getFunctionGroups(metaClass);
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionCList overloads;
- for (const auto &func : qAsConst(it.value())) {
+ for (const auto &func : std::as_const(it.value())) {
if (func->isAssignmentOperator() || func->isConversionOperator()
|| func->isModifiedRemoved()
|| func->isPrivate() || func->ownerClass() != func->implementingClass()
@@ -1827,7 +1930,8 @@ AbstractMetaFunctionCList
return methods;
}
-const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass *metaClass)
+AbstractMetaClassCPtr
+ ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClassCPtr &metaClass)
{
if (!metaClass || metaClass->baseClassNames().isEmpty())
return nullptr;
@@ -1838,24 +1942,48 @@ const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const Abs
QString ShibokenGenerator::getModuleHeaderFileBaseName(const QString &moduleName)
{
- return moduleCppPrefix(moduleName).toLower() + QStringLiteral("_python");
+ return moduleCppPrefix(moduleName).toLower() + "_python"_L1;
}
QString ShibokenGenerator::getModuleHeaderFileName(const QString &moduleName)
{
- return getModuleHeaderFileBaseName(moduleName) + QStringLiteral(".h");
+ return getModuleHeaderFileBaseName(moduleName) + ".h"_L1;
}
QString ShibokenGenerator::getPrivateModuleHeaderFileName(const QString &moduleName)
{
- return getModuleHeaderFileBaseName(moduleName) + QStringLiteral("_p.h");
+ return getModuleHeaderFileBaseName(moduleName) + "_p.h"_L1;
+}
+
+IncludeGroupList ShibokenGenerator::classIncludes(const AbstractMetaClassCPtr &metaClass) const
+{
+ IncludeGroupList result;
+ const auto typeEntry = metaClass->typeEntry();
+ //Extra includes
+ result.append(IncludeGroup{u"Extra includes"_s,
+ typeEntry->extraIncludes()});
+
+ result.append({u"Enum includes"_s, {}});
+ for (const auto &cppEnum : metaClass->enums())
+ result.back().includes.append(cppEnum.typeEntry()->extraIncludes());
+
+ result.append({u"Argument includes"_s, typeEntry->argumentIncludes()});
+ const auto implicitConvs = implicitConversions(typeEntry);
+ for (const auto &f : implicitConvs) {
+ if (f->isConversionOperator()) {
+ const auto source = f->ownerClass();
+ Q_ASSERT(source);
+ result.back().append(source->typeEntry()->include());
+ }
+ }
+ return result;
}
/*
static void dumpFunction(AbstractMetaFunctionList lst)
{
qDebug() << "DUMP FUNCTIONS: ";
- for (AbstractMetaFunction *func : qAsConst(lst))
+ for (AbstractMetaFunction *func : std::as_const(lst))
qDebug() << "*" << func->ownerClass()->name()
<< func->signature()
<< "Private: " << func->isPrivate()
@@ -1899,29 +2027,47 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() c
{
FunctionGroups results;
insertIntoFunctionGroups(api().globalFunctions(), &results);
- for (auto nsp : invisibleTopNamespaces())
+ for (const auto &nsp : invisibleTopNamespaces())
insertIntoFunctionGroups(nsp->functions(), &results);
return results;
}
-const GeneratorClassInfoCacheEntry &ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClass *scope)
+const GeneratorClassInfoCacheEntry &
+ ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClassCPtr &scope)
{
auto cache = generatorClassInfoCache();
auto it = cache->find(scope);
if (it == cache->end()) {
it = cache->insert(scope, {});
- it.value().functionGroups = getFunctionGroupsImpl(scope);
- it.value().needsGetattroFunction = classNeedsGetattroFunctionImpl(scope);
+ auto &entry = it.value();
+ entry.functionGroups = getFunctionGroupsImpl(scope);
+ entry.needsGetattroFunction = classNeedsGetattroFunctionImpl(scope);
+ entry.numberProtocolOperators = getNumberProtocolOperators(scope);
+ entry.boolCastFunctionO = getBoolCast(scope);
}
return it.value();
}
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const AbstractMetaClass *scope)
+ShibokenGenerator::FunctionGroups
+ ShibokenGenerator::getFunctionGroups(const AbstractMetaClassCPtr &scope)
{
Q_ASSERT(scope);
return getGeneratorClassInfo(scope).functionGroups;
}
+QList<AbstractMetaFunctionCList>
+ ShibokenGenerator::numberProtocolOperators(const AbstractMetaClassCPtr &scope)
+{
+ Q_ASSERT(scope);
+ return getGeneratorClassInfo(scope).numberProtocolOperators;
+}
+
+BoolCastFunctionOptional ShibokenGenerator::boolCast(const AbstractMetaClassCPtr &scope)
+{
+ Q_ASSERT(scope);
+ return getGeneratorClassInfo(scope).boolCastFunctionO;
+}
+
// Use non-const overloads only, for example, "foo()" and "foo()const"
// the second is removed.
static void removeConstOverloads(AbstractMetaFunctionCList *overloads)
@@ -1930,7 +2076,7 @@ static void removeConstOverloads(AbstractMetaFunctionCList *overloads)
const auto &f = overloads->at(i);
if (f->isConstant()) {
for (qsizetype c = 0, size = overloads->size(); c < size; ++c) {
- if (f->isConstOverloadOf(overloads->at(c).data())) {
+ if (f->isConstOverloadOf(overloads->at(c).get())) {
overloads->removeAt(i);
break;
}
@@ -1939,7 +2085,8 @@ static void removeConstOverloads(AbstractMetaFunctionCList *overloads)
}
}
-ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope)
+ShibokenGenerator::FunctionGroups
+ ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClassCPtr &scope)
{
AbstractMetaFunctionCList lst = scope->functions();
scope->getFunctionsFromInvisibleNamespacesToBeGenerated(&lst);
@@ -1970,13 +2117,156 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const
return results;
}
+static bool removeNumberProtocolOperator(const AbstractMetaFunctionCPtr &f)
+{
+ return !f->generateBinding()
+ || (f->ownerClass() != f->implementingClass() && !f->isAbstract());
+}
+
+QList<AbstractMetaFunctionCList>
+ ShibokenGenerator::getNumberProtocolOperators(const AbstractMetaClassCPtr &metaClass)
+{
+ QList<AbstractMetaFunctionCList> result;
+ if (metaClass->isNamespace())
+ return result;
+ result = filterGroupedOperatorFunctions(
+ metaClass,
+ OperatorQueryOption::ArithmeticOp
+ | OperatorQueryOption::IncDecrementOp
+ | OperatorQueryOption::LogicalOp
+ | OperatorQueryOption::BitwiseOp
+ | OperatorQueryOption::ConversionOp);
+
+ for (auto i = result.size() - 1; i >= 0; --i) {
+ AbstractMetaFunctionCList &l = result[i];
+ auto rend = std::remove_if(l.begin(), l.end(), removeNumberProtocolOperator);
+ l.erase(rend, l.end());
+ if (l.isEmpty())
+ result.removeAt(i);
+ }
+
+ return result;
+}
+
+BoolCastFunctionOptional
+ShibokenGenerator::getBoolCast(const AbstractMetaClassCPtr &metaClass)
+{
+ if (metaClass->isNamespace())
+ return std::nullopt;
+
+ const auto te = metaClass->typeEntry();
+ if (te->isSmartPointer()) {
+ auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(te);
+
+ auto valueCheckMethod = ste->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty()) {
+ const auto func = metaClass->findFunction(valueCheckMethod);
+ if (!func)
+ throw Exception(msgMethodNotFound(metaClass, valueCheckMethod));
+ return BoolCastFunction{func, false};
+ }
+
+ auto nullCheckMethod = ste->nullCheckMethod();
+ if (!nullCheckMethod.isEmpty()) {
+ const auto func = metaClass->findFunction(nullCheckMethod);
+ if (!func)
+ throw Exception(msgMethodNotFound(metaClass, nullCheckMethod));
+ return BoolCastFunction{func, true};
+ }
+ }
+
+ auto mode = te->operatorBoolMode();
+ if (useOperatorBoolAsNbBool()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findOperatorBool();
+ if (func)
+ return BoolCastFunction{func, false};
+ }
+
+ mode = te->isNullMode();
+ if (useIsNullAsNbBool()
+ ? mode != TypeSystem::BoolCast::Disabled : mode == TypeSystem::BoolCast::Enabled) {
+ const auto func = metaClass->findQtIsNullMethod();
+ if (func)
+ return BoolCastFunction{func, true};
+ }
+ return std::nullopt;
+}
+
+static bool isInplaceAdd(const AbstractMetaFunctionCPtr &func)
+{
+ return func->name() == u"operator+=";
+}
+
+static bool isIncrementOperator(const AbstractMetaFunctionCPtr &func)
+{
+ return func->functionType() == AbstractMetaFunction::IncrementOperator;
+}
+
+static bool isDecrementOperator(const AbstractMetaFunctionCPtr &func)
+{
+ return func->functionType() == AbstractMetaFunction::DecrementOperator;
+}
+
+// Filter predicate for operator functions
+static bool skipOperatorFunc(const AbstractMetaFunctionCPtr &func)
+{
+ if (func->isModifiedRemoved() || func->usesRValueReferences())
+ return true;
+ const auto &name = func->name();
+ return name == u"operator[]" || name == u"operator->" || name == u"operator!"
+ || name == u"operator/="; // __idiv__ is not needed in Python3
+}
+
+QList<AbstractMetaFunctionCList>
+ShibokenGenerator::filterGroupedOperatorFunctions(const AbstractMetaClassCPtr &metaClass,
+ OperatorQueryOptions query)
+{
+ // ( func_name, num_args ) => func_list
+ QMap<std::pair<QString, int>, AbstractMetaFunctionCList> results;
+ auto funcs = metaClass->operatorOverloads(query);
+ auto end = std::remove_if(funcs.begin(), funcs.end(), skipOperatorFunc);
+ funcs.erase(end, funcs.end());
+ // If we have operator+=, we remove the operator++/-- which would
+ // otherwise be used for emulating __iadd__, __isub__.
+ if (std::any_of(funcs.cbegin(), funcs.cend(), isInplaceAdd)) {
+ end = std::remove_if(funcs.begin(), funcs.end(),
+ [] (const AbstractMetaFunctionCPtr &func) {
+ return func->isIncDecrementOperator();
+ });
+ funcs.erase(end, funcs.end());
+ } else {
+ // If both prefix/postfix ++/-- are present, remove one
+ if (std::count_if(funcs.begin(), funcs.end(), isIncrementOperator) > 1)
+ funcs.erase(std::find_if(funcs.begin(), funcs.end(), isIncrementOperator));
+ if (std::count_if(funcs.begin(), funcs.end(), isDecrementOperator) > 1)
+ funcs.erase(std::find_if(funcs.begin(), funcs.end(), isDecrementOperator));
+ }
+ for (const auto &func : funcs) {
+ int args;
+ if (func->isComparisonOperator()) {
+ args = -1;
+ } else {
+ args = func->arguments().size();
+ }
+ auto op = std::make_pair(func->name(), args);
+ results[op].append(func);
+ }
+ QList<AbstractMetaFunctionCList> result;
+ result.reserve(results.size());
+ for (auto it = results.cbegin(), end = results.cend(); it != end; ++it)
+ result.append(it.value());
+ return result;
+}
+
static bool hidesBaseClassFunctions(const AbstractMetaFunctionCPtr &f)
{
- return 0 == (f->attributes()
- & (AbstractMetaFunction::OverriddenCppMethod | AbstractMetaFunction::FinalCppMethod));
+ auto attributes = f->cppAttributes();
+ return !attributes.testFlag(FunctionAttribute::Override)
+ && !attributes.testFlag(FunctionAttribute::Final);
}
-void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClass *scope,
+void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClassCPtr &scope,
AbstractMetaFunctionCList *overloads)
{
if (overloads->isEmpty() || scope->isNamespace() || scope->baseClasses().isEmpty())
@@ -2002,7 +2292,8 @@ void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClass *scope,
AbstractMetaFunctionCList baseCandidates;
- auto basePredicate = [&functionName, &seenSignatures, &baseCandidates](const AbstractMetaClass *b) {
+ auto basePredicate = [&functionName, &seenSignatures, &baseCandidates]
+ (const AbstractMetaClassCPtr &b) {
for (const auto &f : b->functions()) {
if (f->generateBinding() && f->name() == functionName) {
const QString signature = f->minimalSignature();
@@ -2015,7 +2306,7 @@ void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClass *scope,
return false; // Keep going
};
- for (const auto *baseClass : scope->baseClasses())
+ for (const auto &baseClass : scope->baseClasses())
recurseClassHierarchy(baseClass, basePredicate);
// Remove the ones that are not made visible with using declarations
@@ -2045,83 +2336,108 @@ void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClass *scope,
}
}
-Generator::OptionDescriptions ShibokenGenerator::options() const
+QList<OptionDescription> ShibokenGenerator::options()
{
- auto result = Generator::options();
- result.append({
- {QLatin1StringView(DISABLE_VERBOSE_ERROR_MESSAGES),
+ return {
+ {DISABLE_VERBOSE_ERROR_MESSAGES,
u"Disable verbose error messages. Turn the python code hard to debug\n"
"but safe few kB on the generated bindings."_s},
- {QLatin1StringView(PARENT_CTOR_HEURISTIC),
+ {PARENT_CTOR_HEURISTIC,
u"Enable heuristics to detect parent relationship on constructors."_s},
- {QLatin1StringView(RETURN_VALUE_HEURISTIC),
+ {RETURN_VALUE_HEURISTIC,
u"Enable heuristics to detect parent relationship on return values\n"
"(USE WITH CAUTION!)"_s},
- {QLatin1StringView(USE_ISNULL_AS_NB_NONZERO),
+ {USE_ISNULL_AS_NB_BOOL,
u"If a class have an isNull() const method, it will be used to compute\n"
"the value of boolean casts"_s},
- {QLatin1StringView(USE_OPERATOR_BOOL_AS_NB_NONZERO),
+ {LEAN_HEADERS,
+ u"Forward declare classes in module headers"_s},
+ {USE_OPERATOR_BOOL_AS_NB_BOOL,
u"If a class has an operator bool, it will be used to compute\n"
"the value of boolean casts"_s},
- {QLatin1StringView(NO_IMPLICIT_CONVERSIONS),
+ {NO_IMPLICIT_CONVERSIONS,
u"Do not generate implicit_conversions for function arguments."_s},
- {QLatin1StringView(WRAPPER_DIAGNOSTICS),
+ {WRAPPER_DIAGNOSTICS,
u"Generate diagnostic code around wrappers"_s}
- });
- return result;
+ };
}
-bool ShibokenGenerator::handleOption(const QString &key, const QString &value)
+class ShibokenGeneratorOptionsParser : public OptionsParser
{
- if (Generator::handleOption(key, value))
- return true;
- if (key == QLatin1StringView(PARENT_CTOR_HEURISTIC))
- return (m_useCtorHeuristic = true);
- if (key == QLatin1StringView(RETURN_VALUE_HEURISTIC))
- return (m_userReturnValueHeuristic = true);
- if (key == QLatin1StringView(DISABLE_VERBOSE_ERROR_MESSAGES))
- return (m_verboseErrorMessagesDisabled = true);
- if (key == QLatin1StringView(USE_ISNULL_AS_NB_NONZERO))
- return (m_useIsNullAsNbNonZero = true);
- if (key == QLatin1StringView(USE_OPERATOR_BOOL_AS_NB_NONZERO))
- return (m_useOperatorBoolAsNbNonZero = true);
- if (key == QLatin1StringView(NO_IMPLICIT_CONVERSIONS)) {
- return m_generateImplicitConversions = false;
+public:
+ explicit ShibokenGeneratorOptionsParser(ShibokenGeneratorOptions *o) : m_options(o) {}
+
+ bool handleBoolOption(const QString & key, OptionSource source) override;
+
+private:
+ ShibokenGeneratorOptions *m_options;
+};
+
+bool ShibokenGeneratorOptionsParser::handleBoolOption(const QString &key, OptionSource source)
+{
+ if (source == OptionSource::CommandLineSingleDash)
+ return false;
+ if (key == PARENT_CTOR_HEURISTIC)
+ return (m_options->useCtorHeuristic = true);
+ if (key == RETURN_VALUE_HEURISTIC)
+ return (m_options->userReturnValueHeuristic = true);
+ if (key == DISABLE_VERBOSE_ERROR_MESSAGES)
+ return (m_options->verboseErrorMessagesDisabled = true);
+ if (key == USE_ISNULL_AS_NB_BOOL || key == USE_ISNULL_AS_NB_NONZERO) {
+ return (m_options->useIsNullAsNbBool = true);
+ }
+ if (key == LEAN_HEADERS)
+ return (m_options->leanHeaders= true);
+ if (key == USE_OPERATOR_BOOL_AS_NB_BOOL || key == USE_OPERATOR_BOOL_AS_NB_NONZERO) {
+ return (m_options->useOperatorBoolAsNbBool = true);
+ }
+ if (key == NO_IMPLICIT_CONVERSIONS) {
+ m_options->generateImplicitConversions = false;
return true;
}
- if (key == QLatin1StringView(WRAPPER_DIAGNOSTICS))
- return (m_wrapperDiagnostics = true);
+ if (key == WRAPPER_DIAGNOSTICS)
+ return (m_options->wrapperDiagnostics = true);
return false;
}
+std::shared_ptr<OptionsParser> ShibokenGenerator::createOptionsParser()
+{
+ return std::make_shared<ShibokenGeneratorOptionsParser>(&m_options);
+}
+
bool ShibokenGenerator::doSetup()
{
return true;
}
-bool ShibokenGenerator::useCtorHeuristic() const
+bool ShibokenGenerator::useCtorHeuristic()
+{
+ return m_options.useCtorHeuristic;
+}
+
+bool ShibokenGenerator::useReturnValueHeuristic()
{
- return m_useCtorHeuristic;
+ return m_options.userReturnValueHeuristic;
}
-bool ShibokenGenerator::useReturnValueHeuristic() const
+bool ShibokenGenerator::useIsNullAsNbBool()
{
- return m_userReturnValueHeuristic;
+ return m_options.useIsNullAsNbBool;
}
-bool ShibokenGenerator::useIsNullAsNbNonZero() const
+bool ShibokenGenerator::leanHeaders()
{
- return m_useIsNullAsNbNonZero;
+ return m_options.leanHeaders;
}
-bool ShibokenGenerator::useOperatorBoolAsNbNonZero() const
+bool ShibokenGenerator::useOperatorBoolAsNbBool()
{
- return m_useOperatorBoolAsNbNonZero;
+ return m_options.useOperatorBoolAsNbBool;
}
-bool ShibokenGenerator::generateImplicitConversions() const
+bool ShibokenGenerator::generateImplicitConversions()
{
- return m_generateImplicitConversions;
+ return m_options.generateImplicitConversions;
}
QString ShibokenGenerator::moduleCppPrefix(const QString &moduleName)
@@ -2131,19 +2447,24 @@ QString ShibokenGenerator::moduleCppPrefix(const QString &moduleName)
return result;
}
+QString ShibokenGenerator::cppApiVariableNameOld(const QString &moduleName)
+{
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "Types"_L1;
+}
+
QString ShibokenGenerator::cppApiVariableName(const QString &moduleName)
{
- return u"Sbk"_s + moduleCppPrefix(moduleName) + u"Types"_s;
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "TypeStructs"_L1;
}
QString ShibokenGenerator::pythonModuleObjectName(const QString &moduleName)
{
- return u"Sbk"_s + moduleCppPrefix(moduleName) + u"ModuleObject"_s;
+ return "Sbk"_L1 + moduleCppPrefix(moduleName) + "ModuleObject"_L1;
}
QString ShibokenGenerator::convertersVariableName(const QString &moduleName)
{
- QString result = cppApiVariableName(moduleName);
+ QString result = cppApiVariableNameOld(moduleName);
result.chop(1);
result.append(u"Converters"_s);
return result;
@@ -2151,11 +2472,11 @@ QString ShibokenGenerator::convertersVariableName(const QString &moduleName)
static QString processInstantiationsVariableName(const AbstractMetaType &type)
{
- QString res = u'_' + _fixedCppTypeName(type.typeEntry()->qualifiedCppName()).toUpper();
+ QString res = u'_' + _fixedCppTypeName(type.typeEntry()->qualifiedCppName());
for (const auto &instantiation : type.instantiations()) {
res += instantiation.isContainer()
? processInstantiationsVariableName(instantiation)
- : u'_' + _fixedCppTypeName(instantiation.cppSignature()).toUpper();
+ : u'_' + _fixedCppTypeName(instantiation.cppSignature());
}
return res;
}
@@ -2164,29 +2485,30 @@ static void appendIndexSuffix(QString *s)
{
if (!s->endsWith(u'_'))
s->append(u'_');
- s->append(QStringLiteral("IDX"));
+ s->append("IDX"_L1);
}
-QString ShibokenGenerator::getTypeAlternateTemplateIndexVariableName(const AbstractMetaClass *metaClass)
+QString
+ ShibokenGenerator::getTypeAlternateTemplateIndexVariableName(const AbstractMetaClassCPtr &metaClass)
{
- const AbstractMetaClass *templateBaseClass = metaClass->templateBaseClass();
+ const auto templateBaseClass = metaClass->templateBaseClass();
Q_ASSERT(templateBaseClass);
QString result = u"SBK_"_s
- + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper();
+ + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName());
for (const auto &instantiation : metaClass->templateBaseClassInstantiations())
result += processInstantiationsVariableName(instantiation);
appendIndexSuffix(&result);
return result;
}
-QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *metaClass)
+QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClassCPtr &metaClass)
{
return getTypeIndexVariableName(metaClass->typeEntry());
}
-QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type)
+QString ShibokenGenerator::getTypeIndexVariableName(TypeEntryCPtr type)
{
- if (type->isCppPrimitive())
- type = type->asPrimitive()->basicReferencedTypeEntry();
+ if (isCppPrimitive(type))
+ type = basicReferencedTypeEntry(type);
QString result = u"SBK_"_s;
// Disambiguate namespaces per module to allow for extending them.
if (type->isNamespace()) {
@@ -2194,7 +2516,7 @@ QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type)
const int dot = package.lastIndexOf(u'.');
result += QStringView{package}.right(package.size() - (dot + 1));
}
- result += _fixedCppTypeName(type->qualifiedCppName()).toUpper();
+ result += _fixedCppTypeName(type->qualifiedCppName());
appendIndexSuffix(&result);
return result;
}
@@ -2202,15 +2524,48 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType &type
{
QString result = u"SBK"_s;
if (type.typeEntry()->isContainer())
- result += u'_' + moduleName().toUpper();
+ result += u'_' + moduleName();
result += processInstantiationsVariableName(type);
appendIndexSuffix(&result);
return result;
}
-bool ShibokenGenerator::verboseErrorMessagesDisabled() const
+void collectfromTypeEntry(TypeEntryCPtr entry, QStringList &typeNames)
+{
+ if (entry->shouldGenerate()) {
+ typeNames[entry->sbkIndex()] = entry->qualifiedTargetLangName();
+ if (entry->isEnum()) {
+ auto ete = std::static_pointer_cast<const EnumTypeEntry>(entry);
+ if (ete->flags()) {
+ auto entry = ete->flags();
+ typeNames[entry->sbkIndex()] = entry->qualifiedTargetLangName();
+ }
+ }
+ }
+}
+
+void ShibokenGenerator::collectFullTypeNamesArray(QStringList &typeNames)
+{
+ for (const auto &metaClass : api().classes()) {
+ collectfromTypeEntry(metaClass->typeEntry(), typeNames);
+
+ for (const AbstractMetaEnum &metaEnum : metaClass->enums())
+ collectfromTypeEntry(metaEnum.typeEntry(), typeNames);
+
+ int smartPointerCountIndex = getMaxTypeIndex();
+ for (const auto &smp : api().instantiatedSmartPointers()) {
+ auto entry = smp.type.typeEntry();
+ typeNames[smartPointerCountIndex] = entry->qualifiedTargetLangName();
+ ++smartPointerCountIndex;
+ }
+ }
+ for (const AbstractMetaEnum &metaEnum : api().globalEnums())
+ collectfromTypeEntry(metaEnum.typeEntry(), typeNames);
+}
+
+bool ShibokenGenerator::verboseErrorMessagesDisabled()
{
- return m_verboseErrorMessagesDisabled;
+ return m_options.verboseErrorMessagesDisabled;
}
bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const AbstractMetaFunctionCPtr &func) const
@@ -2240,9 +2595,9 @@ QString ShibokenGenerator::minimalConstructorExpression(const ApiExtractorResult
}
QString ShibokenGenerator::minimalConstructorExpression(const ApiExtractorResult &api,
- const TypeEntry *type)
+ const TypeEntryCPtr &type)
{
- if (type->isExtendedCppPrimitive())
+ if (isExtendedCppPrimitive(type))
return {};
const auto ctor = minimalConstructor(api, type);
if (ctor.has_value())
@@ -2263,7 +2618,7 @@ QString ShibokenGenerator::pythonArgsAt(int i)
void ShibokenGenerator::replaceTemplateVariables(QString &code,
const AbstractMetaFunctionCPtr &func) const
{
- const AbstractMetaClass *cpp_class = func->ownerClass();
+ const auto cpp_class = func->ownerClass();
if (cpp_class)
code.replace(u"%TYPE"_s, cpp_class->name());
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index 767af579d..22ee73fa2 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -6,20 +6,37 @@
#include <generator.h>
-#include "customconversion.h"
+#include "customconversion_typedefs.h"
+#include "abstractmetalang_enums.h"
+#include "typesystem_typedefs.h"
+#include "typesystem_enums.h"
#include <QtCore/QRegularExpression>
#include <array>
+#include <optional>
+class EnumTypeEntry;
+class FlagsTypeEntry;
class DocParser;
class CodeSnip;
class QPropertySpec;
class OverloadData;
-class TextStream;
+class TargetToNativeConversion;
struct GeneratorClassInfoCacheEntry;
+struct IncludeGroup;
+struct ShibokenGeneratorOptions;
+
+class TextStream;
-QT_FORWARD_DECLARE_CLASS(TextStream)
+// Function to be used for implementing nb_bool
+struct BoolCastFunction
+{
+ AbstractMetaFunctionCPtr function;
+ bool invert = false; // Function is "isNull()", (invert result).
+};
+
+using BoolCastFunctionOptional = std::optional<BoolCastFunction>;
/**
* Abstract generator that contains common methods used in CppGenerator and HeaderGenerator.
@@ -27,6 +44,8 @@ QT_FORWARD_DECLARE_CLASS(TextStream)
class ShibokenGenerator : public Generator
{
public:
+ Q_DISABLE_COPY_MOVE(ShibokenGenerator)
+
/// Besides the actual bindings (see AbstractMetaFunction::generateBinding(),
/// some functions need to be generated into the wrapper class
/// (virtual method/avoid protected hack expose).
@@ -70,15 +89,18 @@ public:
const char *name() const override { return "Shiboken"; }
+ static QList<OptionDescription> options();
+ static std::shared_ptr<OptionsParser> createOptionsParser();
+
static QString minimalConstructorExpression(const ApiExtractorResult &api,
const AbstractMetaType &type);
static QString minimalConstructorExpression(const ApiExtractorResult &api,
- const TypeEntry *type);
+ const TypeEntryCPtr &type);
protected:
bool doSetup() override;
- GeneratorContext contextForClass(const AbstractMetaClass *c) const override;
+ GeneratorContext contextForClass(const AbstractMetaClassCPtr &c) const override;
/**
* Returns a map with all functions grouped, the function name is used as key.
@@ -86,7 +108,12 @@ protected:
* \param scope Where to search for functions, null means all global functions.
*/
FunctionGroups getGlobalFunctionGroups() const;
- static FunctionGroups getFunctionGroups(const AbstractMetaClass *scope);
+ static FunctionGroups getFunctionGroups(const AbstractMetaClassCPtr &scope);
+
+ static QList<AbstractMetaFunctionCList>
+ numberProtocolOperators(const AbstractMetaClassCPtr &scope);
+
+ static BoolCastFunctionOptional boolCast(const AbstractMetaClassCPtr &scope);
/**
* Returns all different inherited overloads of func, and includes func as well.
@@ -118,6 +145,7 @@ protected:
/// Replaces variables for the user's custom code at global or class level.
void processCodeSnip(QString &code) const;
+ void processCodeSnip(QString &code, const QString &context) const;
void processClassCodeSnip(QString &code, const GeneratorContext &context) const;
/**
@@ -143,145 +171,166 @@ protected:
int arg_count = -1) const;
/// Returns the top-most class that has multiple inheritance in the ancestry.
- static const AbstractMetaClass *getMultipleInheritingClass(const AbstractMetaClass *metaClass);
+ static AbstractMetaClassCPtr
+ getMultipleInheritingClass(const AbstractMetaClassCPtr &metaClass);
- static bool useOverrideCaching(const AbstractMetaClass *metaClass);
- AttroCheck checkAttroFunctionNeeds(const AbstractMetaClass *metaClass) const;
+ static bool useOverrideCaching(const AbstractMetaClassCPtr &metaClass);
+ static AttroCheck checkAttroFunctionNeeds(const AbstractMetaClassCPtr &metaClass);
- /// Returns a list of methods of the given class where each one is part of a different overload with both static and non-static method.
+ /// Returns a list of methods of the given class where each one is part of
+ /// a different overload with both static and non-static method.
static AbstractMetaFunctionCList
- getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass *metaClass);
+ getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClassCPtr &metaClass);
static void writeToPythonConversion(TextStream &s,
const AbstractMetaType &type,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
const QString &argumentName);
static void writeToCppConversion(TextStream &s,
const AbstractMetaType &type,
- const AbstractMetaClass *context,
const QString &inArgName,
const QString &outArgName);
static void writeToCppConversion(TextStream &s,
- const AbstractMetaClass *metaClass, const QString &inArgName,
+ const AbstractMetaClassCPtr &metaClass,
+ const QString &inArgName,
const QString &outArgName);
/// Returns true if the argument is a pointer that rejects nullptr values.
static bool shouldRejectNullPointerArgument(const AbstractMetaFunctionCPtr &func,
int argIndex);
- /// Verifies if the class should have a C++ wrapper generated for it, instead of only a Python wrapper.
- bool shouldGenerateCppWrapper(const AbstractMetaClass *metaClass) const;
+ /// Verifies if the class should have a C++ wrapper generated for it,
+ /// instead of only a Python wrapper.
+ static bool shouldGenerateCppWrapper(const AbstractMetaClassCPtr &metaClass);
+
+ static bool shouldGenerateMetaObjectFunctions(const AbstractMetaClassCPtr &metaClass);
/// Returns which functions need to be generated into the wrapper class
- FunctionGeneration functionGeneration(const AbstractMetaFunctionCPtr &func) const;
+ static FunctionGeneration functionGeneration(const AbstractMetaFunctionCPtr &func);
// Return a list of implicit conversions if generation is enabled.
- AbstractMetaFunctionCList implicitConversions(const TypeEntry *t) const;
+ AbstractMetaFunctionCList implicitConversions(const TypeEntryCPtr &t) const;
+
+ static QString wrapperName(const AbstractMetaClassCPtr &metaClass);
- QString wrapperName(const AbstractMetaClass *metaClass) const;
+ static QString fullPythonClassName(const AbstractMetaClassCPtr &metaClass);
+
+ static QString headerFileNameForContext(const GeneratorContext &context);
+ IncludeGroup baseWrapperIncludes(const GeneratorContext &classContext) const;
- static QString fullPythonClassName(const AbstractMetaClass *metaClass);
static QString fullPythonFunctionName(const AbstractMetaFunctionCPtr &func, bool forceFunc);
- bool wrapperDiagnostics() const { return m_wrapperDiagnostics; }
+ static bool wrapperDiagnostics();
static QString protectedEnumSurrogateName(const AbstractMetaEnum &metaEnum);
static QString pythonPrimitiveTypeName(const QString &cppTypeName);
static QString pythonOperatorFunctionName(const AbstractMetaFunctionCPtr &func);
+ static QList<AbstractMetaFunctionCList>
+ filterGroupedOperatorFunctions(const AbstractMetaClassCPtr &metaClass,
+ OperatorQueryOptions query);
- static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion *toNative);
+ static QString fixedCppTypeName(const TargetToNativeConversion &toNative);
static QString fixedCppTypeName(const AbstractMetaType &type);
- static QString fixedCppTypeName(const TypeEntry *type, QString typeName = QString());
+ static QString fixedCppTypeName(const TypeEntryCPtr &type, QString typeName = {});
static bool isNumber(const QString &cpythonApiName);
- static bool isNumber(const TypeEntry *type);
+ static bool isNumber(const TypeEntryCPtr &type);
static bool isNumber(const AbstractMetaType &type);
- static bool isPyInt(const TypeEntry *type);
+ static bool isPyInt(const TypeEntryCPtr &type);
static bool isPyInt(const AbstractMetaType &type);
static bool isNullPtr(const QString &value);
static QString converterObject(const AbstractMetaType &type) ;
- static QString converterObject(const TypeEntry *type);
+ static QString converterObject(const TypeEntryCPtr &type);
- static QString cpythonBaseName(const AbstractMetaClass *metaClass);
- static QString cpythonBaseName(const TypeEntry *type);
+ static QString cpythonBaseName(const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonBaseName(const TypeEntryCPtr &type);
+ static QString containerCpythonBaseName(const ContainerTypeEntryCPtr &ctype);
static QString cpythonBaseName(const AbstractMetaType &type);
- static QString cpythonTypeName(const AbstractMetaClass *metaClass);
- static QString cpythonTypeName(const TypeEntry *type);
- static QString cpythonTypeNameExt(const TypeEntry *type);
- static QString cpythonTypeNameExt(const AbstractMetaType &type) ;
- static QString cpythonCheckFunction(const TypeEntry *type);
+ static QString cpythonTypeName(const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonTypeName(const TypeEntryCPtr &type);
+ static QString cpythonTypeNameExtSet(const TypeEntryCPtr &type);
+ static QString cpythonTypeNameExtSet(const AbstractMetaType &type);
+ static QString cpythonTypeNameExt(const TypeEntryCPtr &type);
+ static QString cpythonTypeNameExt(const AbstractMetaType &type);
+ static QString cpythonCheckFunction(TypeEntryCPtr type);
static QString cpythonCheckFunction(AbstractMetaType metaType);
- static QString cpythonIsConvertibleFunction(const TypeEntry *type);
- static QString cpythonIsConvertibleFunction(AbstractMetaType metaType);
+ static QString cpythonIsConvertibleFunction(const TypeEntryCPtr &type);
+ static QString cpythonIsConvertibleFunction(const AbstractMetaType &metaType);
static QString cpythonIsConvertibleFunction(const AbstractMetaArgument &metaArg);
- static QString cpythonToCppConversionFunction(const AbstractMetaClass *metaClass) ;
- static QString cpythonToCppConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass *context = nullptr);
- static QString cpythonToPythonConversionFunction(const AbstractMetaType &type,
- const AbstractMetaClass *context = nullptr);
- static QString cpythonToPythonConversionFunction(const AbstractMetaClass *metaClass);
- static QString cpythonToPythonConversionFunction(const TypeEntry *type);
+ static QString cpythonToCppConversionFunction(const AbstractMetaClassCPtr &metaClass) ;
+ static QString cpythonToCppConversionFunction(const AbstractMetaType &type);
+ static QString cpythonToPythonConversionFunction(const AbstractMetaType &type);
+ static QString cpythonToPythonConversionFunction(const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonToPythonConversionFunction(const TypeEntryCPtr &type);
static QString cpythonFunctionName(const AbstractMetaFunctionCPtr &func) ;
static QString cpythonMethodDefinitionName(const AbstractMetaFunctionCPtr &func);
- static QString cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass);
- static QString cpythonGetattroFunctionName(const AbstractMetaClass *metaClass);
- static QString cpythonSetattroFunctionName(const AbstractMetaClass *metaClass);
+ static QString cpythonGettersSettersDefinitionName(const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonGetattroFunctionName(const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonSetattroFunctionName(const AbstractMetaClassCPtr &metaClass);
static QString cpythonGetterFunctionName(const AbstractMetaField &metaField);
static QString cpythonSetterFunctionName(const AbstractMetaField &metaField);
static QString cpythonGetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass);
+ const AbstractMetaClassCPtr &metaClass);
static QString cpythonSetterFunctionName(const QPropertySpec &property,
- const AbstractMetaClass *metaClass);
- static QString cpythonWrapperCPtr(const AbstractMetaClass *metaClass,
- const QString &argName = QStringLiteral("self"));
- static QString cpythonWrapperCPtr(const AbstractMetaType &metaType,
+ const AbstractMetaClassCPtr &metaClass);
+ static QString cpythonWrapperCPtr(const AbstractMetaClassCPtr &metaClass,
+ const QString &argName = QLatin1StringView("self"));
+ static QString cpythonWrapperCPtr(const AbstractMetaType &metaType,
const QString &argName);
- static QString cpythonWrapperCPtr(const TypeEntry *type, const QString &argName);
+ static QString cpythonWrapperCPtr(const TypeEntryCPtr &type, const QString &argName);
- static QString cpythonEnumName(const EnumTypeEntry *enumEntry);
+ static QString cpythonEnumName(const EnumTypeEntryCPtr &enumEntry);
static QString cpythonEnumName(const AbstractMetaEnum &metaEnum);
- static QString cpythonFlagsName(const FlagsTypeEntry *flagsEntry);
+ static QString cpythonFlagsName(const FlagsTypeEntryCPtr &flagsEntry);
static QString cpythonFlagsName(const AbstractMetaEnum *metaEnum);
- /// Returns the special cast function name, the function used to proper cast class with multiple inheritance.
- static QString cpythonSpecialCastFunctionName(const AbstractMetaClass *metaClass);
+ /// Returns the special cast function name, the function used to proper cast
+ /// class with multiple inheritance.
+ static QString cpythonSpecialCastFunctionName(const AbstractMetaClassCPtr &metaClass);
- /// Returns the file name for the module global header. If no module name is provided the current will be used.
+ /// Returns the file name for the module global header. If no module name
+ /// is provided the current will be used.
static QString getModuleHeaderFileName(const QString &moduleName = QString());
static QString getPrivateModuleHeaderFileName(const QString &moduleName = QString());
- OptionDescriptions options() const override;
- bool handleOption(const QString &key, const QString &value) override;
+ /// Includes for header (native wrapper class) or binding source
+ QList<IncludeGroup> classIncludes(const AbstractMetaClassCPtr &metaClass) const;
/// Returns true if the user enabled the so called "parent constructor heuristic".
- bool useCtorHeuristic() const;
+ static bool useCtorHeuristic();
/// Returns true if the user enabled the so called "return value heuristic".
- bool useReturnValueHeuristic() const;
+ static bool useReturnValueHeuristic();
/// Returns true if the generator should use the result of isNull()const to compute boolean casts.
- bool useIsNullAsNbNonZero() const;
+ static bool useIsNullAsNbBool();
+ /// Whether to generate lean module headers
+ static bool leanHeaders();
/// Returns true if the generator should use operator bool to compute boolean casts.
- bool useOperatorBoolAsNbNonZero() const;
+ static bool useOperatorBoolAsNbBool();
/// Generate implicit conversions of function arguments
- bool generateImplicitConversions() const;
+ static bool generateImplicitConversions();
+ static QString cppApiVariableNameOld(const QString &moduleName = {});
static QString cppApiVariableName(const QString &moduleName = QString());
static QString pythonModuleObjectName(const QString &moduleName = QString());
static QString convertersVariableName(const QString &moduleName = QString());
/// Returns the type index variable name for a given class.
- static QString getTypeIndexVariableName(const AbstractMetaClass *metaClass);
+ static QString getTypeIndexVariableName(const AbstractMetaClassCPtr &metaClass);
/// Returns the type index variable name for a given typedef for a template
/// class instantiation made of the template class and the instantiation values
- static QString getTypeAlternateTemplateIndexVariableName(const AbstractMetaClass *metaClass);
- static QString getTypeIndexVariableName(const TypeEntry *type);
+ static QString getTypeAlternateTemplateIndexVariableName(const AbstractMetaClassCPtr &metaClass);
+ static QString getTypeIndexVariableName(TypeEntryCPtr type);
static QString getTypeIndexVariableName(const AbstractMetaType &type) ;
+ /// Collect all type names as an array for initializing the type/name struct.
+ void collectFullTypeNamesArray(QStringList &typeNames);
+
/// Returns true if the user don't want verbose error messages on the generated bindings.
- bool verboseErrorMessagesDisabled() const;
+ static bool verboseErrorMessagesDisabled();
void collectContainerTypesFromConverterMacros(const QString &code, bool toPythonMacro);
@@ -289,16 +338,14 @@ protected:
const AbstractMetaFunctionCPtr &metaFunc,
Options options = NoOption);
- static void writeUnusedVariableCast(TextStream &s, const QString &variableName);
-
// All data about extended converters: the type entries of the target type, and a
// list of AbstractMetaClasses accepted as argument for the conversion.
- using ExtendedConverterData = QHash<const TypeEntry *, AbstractMetaClassCList>;
+ using ExtendedConverterData = QHash<TypeEntryCPtr, AbstractMetaClassCList>;
/// Returns all extended conversions for the current module.
ExtendedConverterData getExtendedConverters() const;
/// Returns a list of converters for the non wrapper types of the current module.
- static QList<const CustomConversion *> getPrimitiveCustomConversions() ;
+ static QList<CustomConversionPtr> getPrimitiveCustomConversions();
/// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments.
bool pythonFunctionWrapperUsesListOfArguments(const AbstractMetaFunctionCPtr &func) const;
@@ -316,16 +363,20 @@ protected:
private:
static QString getModuleHeaderFileBaseName(const QString &moduleName = QString());
static QString cpythonGetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass);
+ const AbstractMetaClassCPtr &enclosingClass);
static QString cpythonSetterFunctionName(const QString &name,
- const AbstractMetaClass *enclosingClass);
+ const AbstractMetaClassCPtr &enclosingClass);
- static const GeneratorClassInfoCacheEntry &getGeneratorClassInfo(const AbstractMetaClass *scope);
- static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClass *scope);
- static bool classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass);
+ static const GeneratorClassInfoCacheEntry &
+ getGeneratorClassInfo(const AbstractMetaClassCPtr &scope);
+ static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClassCPtr &scope);
+ static QList<AbstractMetaFunctionCList>
+ getNumberProtocolOperators(const AbstractMetaClassCPtr &metaClass);
+ static BoolCastFunctionOptional getBoolCast(const AbstractMetaClassCPtr &metaClass);
+ static bool classNeedsGetattroFunctionImpl(const AbstractMetaClassCPtr &metaClass);
QString translateTypeForWrapperMethod(const AbstractMetaType &cType,
- const AbstractMetaClass *context,
+ const AbstractMetaClassCPtr &context,
Options opt = NoOption) const;
/**
@@ -334,7 +385,7 @@ private:
* \param func the metafunction to be searched in subclasses.
* \param seen the function's minimal signatures already seen.
*/
- static void getInheritedOverloads(const AbstractMetaClass *scope,
+ static void getInheritedOverloads(const AbstractMetaClassCPtr &scope,
AbstractMetaFunctionCList *overloads);
@@ -363,7 +414,7 @@ private:
QString functionReturnType(const AbstractMetaFunctionCPtr &func, Options options = NoOption) const;
/// Utility function for writeCodeSnips.
- using ArgumentVarReplacementPair = QPair<AbstractMetaArgument, QString>;
+ using ArgumentVarReplacementPair = std::pair<AbstractMetaArgument, QString>;
using ArgumentVarReplacementList = QList<ArgumentVarReplacementPair>;
static ArgumentVarReplacementList
getArgumentReplacement(const AbstractMetaFunctionCPtr &func,
@@ -425,14 +476,7 @@ private:
void replaceTemplateVariables(QString &code,
const AbstractMetaFunctionCPtr &func) const;
- bool m_useCtorHeuristic = false;
- bool m_userReturnValueHeuristic = false;
- bool m_verboseErrorMessagesDisabled = false;
- bool m_useIsNullAsNbNonZero = false;
- bool m_useOperatorBoolAsNbNonZero = false;
- // FIXME PYSIDE 7 Flip generateImplicitConversions default or remove?
- bool m_generateImplicitConversions = true;
- bool m_wrapperDiagnostics = false;
+ static ShibokenGeneratorOptions m_options;
/// Type system converter variable replacement names and regular expressions.
static const QHash<int, QString> &typeSystemConvName();
@@ -444,20 +488,4 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(ShibokenGenerator::FunctionGeneration);
Q_DECLARE_OPERATORS_FOR_FLAGS(ShibokenGenerator::AttroCheck);
-extern const QString CPP_ARG;
-extern const QString CPP_ARG_REMOVED;
-extern const QString CPP_RETURN_VAR;
-extern const QString CPP_SELF_VAR;
-extern const QString NULL_PTR;
-extern const QString PYTHON_ARG;
-extern const QString PYTHON_ARGS;
-extern const QString PYTHON_OVERRIDE_VAR;
-extern const QString PYTHON_RETURN_VAR;
-extern const QString PYTHON_TO_CPP_VAR;
-extern const QString SMART_POINTER_GETTER;
-
-extern const QString CONV_RULE_OUT_VAR_SUFFIX;
-extern const QString BEGIN_ALLOW_THREADS;
-extern const QString END_ALLOW_THREADS;
-
#endif // SHIBOKENGENERATOR_H
diff --git a/sources/shiboken6/generators/shiboken/shiboken.cpp b/sources/shiboken6/generators/shiboken/shiboken.cpp
deleted file mode 100644
index 193b8e902..000000000
--- a/sources/shiboken6/generators/shiboken/shiboken.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cppgenerator.h"
-#include "headergenerator.h"
-
-EXPORT_GENERATOR_PLUGIN(new CppGenerator << new HeaderGenerator)
diff --git a/sources/shiboken6/icecc.cmake b/sources/shiboken6/icecc.cmake
index b2bf071aa..fa8d3b7cf 100644
--- a/sources/shiboken6/icecc.cmake
+++ b/sources/shiboken6/icecc.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include (CMakeForceCompiler)
option(ENABLE_ICECC "Enable icecc checking, for distributed compilation")
if (ENABLE_ICECC)
diff --git a/sources/shiboken6/libshiboken/CMakeLists.txt b/sources/shiboken6/libshiboken/CMakeLists.txt
index eaed2ef72..b5bbb498a 100644
--- a/sources/shiboken6/libshiboken/CMakeLists.txt
+++ b/sources/shiboken6/libshiboken/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(libshiboken)
option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE)
@@ -27,7 +30,7 @@ if(SHIBOKEN_IS_CROSS_BUILD)
set(host_python_path "${QFP_PYTHON_HOST_PATH}")
set(use_pyc_in_embedding FALSE)
else()
- set(host_python_path "${PYTHON_EXECUTABLE}")
+ set(host_python_path "${Python_EXECUTABLE}")
if(PYTHON_LIMITED_API)
set(use_pyc_in_embedding FALSE)
else()
@@ -55,39 +58,49 @@ set(libshiboken_VERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSIO
set(libshiboken_SOVERSION "${shiboken6_library_so_version}")
set(libshiboken_SRC
-basewrapper.cpp
-debugfreehook.cpp
-gilstate.cpp
-helper.cpp
-sbkarrayconverter.cpp
-sbkcontainer.cpp
-sbkconverter.cpp
-sbkenum.cpp
-sbkerrors.cpp
-sbkfeature_base.cpp
-sbkmodule.cpp
-sbknumpy.cpp
-sbkcppstring.cpp
-sbkstring.cpp
-sbkstaticstrings.cpp
-sbktypefactory.cpp
-bindingmanager.cpp
-threadstatesaver.cpp
-shibokenbuffer.cpp
-pep384impl.cpp
-voidptr.cpp
-bufferprocs_py37.cpp
+autodecref.h
+basewrapper.cpp basewrapper.h basewrapper_p.h
+bindingmanager.cpp bindingmanager.h
+bufferprocs_py37.cpp bufferprocs_py37.h
+debugfreehook.cpp debugfreehook.h
+gilstate.cpp gilstate.h
+helper.cpp helper.h
+pep384impl.cpp pep384impl.h
+pyobjectholder.h
+sbkarrayconverter.cpp sbkarrayconverter.h sbkarrayconverter_p.h
+sbkcontainer.cpp sbkcontainer.h
+sbkconverter.cpp sbkconverter.h sbkconverter_p.h
+sbkcppstring.cpp sbkcppstring.h sbkcpptonumpy.h
+sbkenum.cpp sbkenum.h
+sbkerrors.cpp sbkerrors.h
+sbkfeature_base.cpp sbkfeature_base.h
+sbkmodule.cpp sbkmodule.h
+sbknumpy.cpp sbknumpycheck.h
+sbknumpyview.h
+sbkpython.h
+sbksmartpointer.cpp sbksmartpointer.h
+sbkstaticstrings.cpp sbkstaticstrings.h sbkstaticstrings_p.h
+sbkstring.cpp sbkstring.h
+sbktypefactory.cpp sbktypefactory.h
+sbkwindows.h
+shiboken.h
+shibokenbuffer.cpp shibokenbuffer.h
+shibokenmacros.h
+threadstatesaver.cpp threadstatesaver.h
+voidptr.cpp voidptr.h
embed/signature_bootstrap_inc.h
embed/signature_inc.h
-signature/signature.cpp
+signature/signature.cpp signature.h signature_p.h
signature/signature_globals.cpp
signature/signature_extend.cpp
signature/signature_helper.cpp
)
-set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+# This is needed to let the header obey a variable in "pep384impl.h".
+# Note: This must be set on the cpp file!
+set_property(SOURCE "pep384impl.cpp" PROPERTY SKIP_UNITY_BUILD_INCLUSION ON)
add_library(libshiboken SHARED ${libshiboken_SRC})
add_library(Shiboken6::libshiboken ALIAS libshiboken)
@@ -146,11 +159,12 @@ install(FILES
bindingmanager.h
gilstate.h
helper.h
+ pyobjectholder.h
sbkarrayconverter.h
sbkcontainer.h
sbkconverter.h
+ sbkcpptonumpy.h
sbkenum.h
- sbkenum_p.h
sbkerrors.h
sbkfeature_base.h
sbkmodule.h
@@ -158,6 +172,7 @@ install(FILES
sbknumpyview.h
sbkstring.h
sbkcppstring.h
+ sbksmartpointer.h
sbkstaticstrings.h
sbktypefactory.h
shiboken.h
@@ -165,7 +180,9 @@ install(FILES
threadstatesaver.h
shibokenbuffer.h
sbkpython.h
+ sbkwindows.h
pep384impl.h
+ pep384ext.h
voidptr.h
bufferprocs_py37.h
"${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h"
@@ -179,4 +196,4 @@ install(TARGETS libshiboken EXPORT Shiboken6Targets
ARCHIVE DESTINATION "${LIB_INSTALL_DIR}"
RUNTIME DESTINATION bin)
install(EXPORT Shiboken6Targets NAMESPACE Shiboken6::
- DESTINATION ${LIB_INSTALL_DIR}/cmake/Shiboken6-${shiboken6_VERSION})
+ DESTINATION ${LIB_INSTALL_DIR}/cmake/Shiboken6)
diff --git a/sources/shiboken6/libshiboken/autodecref.h b/sources/shiboken6/libshiboken/autodecref.h
index d2b660676..62a8584e1 100644
--- a/sources/shiboken6/libshiboken/autodecref.h
+++ b/sources/shiboken6/libshiboken/autodecref.h
@@ -5,7 +5,8 @@
#define AUTODECREF_H
#include "sbkpython.h"
-#include "basewrapper.h"
+
+#include <utility>
struct SbkObject;
namespace Shiboken
@@ -14,29 +15,27 @@ namespace Shiboken
/**
* AutoDecRef holds a PyObject pointer and decrement its reference counter when destroyed.
*/
-struct LIBSHIBOKEN_API AutoDecRef
+struct AutoDecRef
{
public:
AutoDecRef(const AutoDecRef &) = delete;
- AutoDecRef(AutoDecRef &&) = delete;
+ AutoDecRef(AutoDecRef &&o) noexcept : m_pyObj{std::exchange(o.m_pyObj, nullptr)} {}
AutoDecRef &operator=(const AutoDecRef &) = delete;
- AutoDecRef &operator=(AutoDecRef &&) = delete;
+ AutoDecRef &operator=(AutoDecRef &&o) noexcept
+ {
+ m_pyObj = std::exchange(o.m_pyObj, nullptr);
+ return *this;
+ }
- /**
- * AutoDecRef constructor.
- * \param pyobj A borrowed reference to a Python object
- */
- explicit AutoDecRef(PyObject *pyObj) : m_pyObj(pyObj) {}
- /**
- * AutoDecRef constructor.
- * \param pyobj A borrowed reference to a Python object
- */
- explicit AutoDecRef(SbkObject *pyObj) : m_pyObj(reinterpret_cast<PyObject *>(pyObj)) {}
- /**
- * AutoDecref constructor.
- * To be used later with reset():
- */
- AutoDecRef() : m_pyObj(nullptr) {}
+ /// AutoDecRef constructor.
+ /// \param pyobj A borrowed reference to a Python object
+ explicit AutoDecRef(PyObject *pyObj) noexcept : m_pyObj(pyObj) {}
+ /// AutoDecRef constructor.
+ /// \param pyobj A borrowed reference to a wrapped Python object
+ explicit AutoDecRef(SbkObject *pyObj) noexcept : m_pyObj(reinterpret_cast<PyObject *>(pyObj)) {}
+ /// AutoDecref default constructor.
+ /// To be used later with reset():
+ AutoDecRef() noexcept = default;
/// Decref the borrowed python reference
~AutoDecRef()
@@ -44,18 +43,19 @@ public:
Py_XDECREF(m_pyObj);
}
- inline bool isNull() const { return m_pyObj == nullptr; }
+ [[nodiscard]] bool isNull() const { return m_pyObj == nullptr; }
/// Returns the pointer of the Python object being held.
- inline PyObject *object() { return m_pyObj; }
- inline operator PyObject *() { return m_pyObj; }
+ [[nodiscard]] PyObject *object() const { return m_pyObj; }
+ [[nodiscard]] operator PyObject *() const { return m_pyObj; }
#ifndef Py_LIMITED_API
- inline operator PyTupleObject *() { return reinterpret_cast<PyTupleObject *>(m_pyObj); }
+ [[deprecated]] inline operator PyTupleObject *()
+ { return reinterpret_cast<PyTupleObject *>(m_pyObj); }
#endif
inline operator bool() const { return m_pyObj != nullptr; }
inline PyObject *operator->() { return m_pyObj; }
template<typename T>
- T cast()
+ [[deprecated]] T cast()
{
return reinterpret_cast<T>(m_pyObj);
}
@@ -79,10 +79,9 @@ public:
}
private:
- PyObject *m_pyObj;
+ PyObject *m_pyObj = nullptr;
};
} // namespace Shiboken
#endif // AUTODECREF_H
-
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index f1622c30b..ef20ea9cf 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -5,9 +5,12 @@
#include "basewrapper_p.h"
#include "bindingmanager.h"
#include "helper.h"
+#include "pep384ext.h"
#include "sbkconverter.h"
#include "sbkenum.h"
+#include "sbkerrors.h"
#include "sbkfeature_base.h"
+#include "sbkmodule.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
@@ -21,6 +24,7 @@
#include <algorithm>
#include "threadstatesaver.h"
#include "signature.h"
+#include "signature_p.h"
#include "voidptr.h"
#include <iostream>
@@ -33,7 +37,73 @@ namespace {
void _destroyParentInfo(SbkObject *obj, bool keepReference);
}
-static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEntries &dts)
+namespace Shiboken
+{
+// Walk through the first level of non-user-type Sbk base classes relevant for
+// C++ object allocation. Return true from the predicate to terminate.
+template <class Predicate>
+bool walkThroughBases(PyTypeObject *currentType, Predicate predicate)
+{
+ PyObject *bases = currentType->tp_bases;
+ const Py_ssize_t numBases = PyTuple_Size(bases);
+ bool result = false;
+ for (Py_ssize_t i = 0; !result && i < numBases; ++i) {
+ auto type = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(bases, i));
+ if (PyType_IsSubtype(type, SbkObject_TypeF()) != 0) {
+ result = PepType_SOTP(type)->is_user_type
+ ? walkThroughBases(type, predicate) : predicate(type);
+ }
+ }
+ return result;
+}
+
+int getTypeIndexOnHierarchy(PyTypeObject *baseType, PyTypeObject *desiredType)
+{
+ int index = -1;
+ walkThroughBases(baseType, [&index, desiredType](PyTypeObject *node) {
+ ++index;
+ return PyType_IsSubtype(node, desiredType) != 0;
+ });
+ return index;
+}
+
+int getNumberOfCppBaseClasses(PyTypeObject *baseType)
+{
+ int count = 0;
+ walkThroughBases(baseType, [&count](PyTypeObject *) {
+ ++count;
+ return false;
+ });
+ return count;
+}
+
+std::vector<PyTypeObject *> getCppBaseClasses(PyTypeObject *baseType)
+{
+ std::vector<PyTypeObject *> cppBaseClasses;
+ walkThroughBases(baseType, [&cppBaseClasses](PyTypeObject *node) {
+ cppBaseClasses.push_back(node);
+ return false;
+ });
+ return cppBaseClasses;
+}
+
+using DestructorEntries = std::vector<DestructorEntry>;
+
+DestructorEntries getDestructorEntries(SbkObject *o)
+{
+ DestructorEntries result;
+ void **cptrs = o->d->cptr;
+ walkThroughBases(Py_TYPE(o), [&result, cptrs](PyTypeObject *node) {
+ auto *sotp = PepType_SOTP(node);
+ auto index = result.size();
+ result.push_back(DestructorEntry{sotp->cpp_dtor,
+ cptrs[index]});
+ return false;
+ });
+ return result;
+}
+
+static void callDestructor(const DestructorEntries &dts)
{
for (const auto &e : dts) {
Shiboken::ThreadStateSaver threadSaver;
@@ -42,6 +112,8 @@ static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEnt
}
}
+} // namespace Shiboken
+
extern "C"
{
@@ -53,7 +125,7 @@ void Sbk_object_dealloc(PyObject *self)
// This was not needed before Python 3.8 (Python issue 35810)
Py_DECREF(Py_TYPE(self));
}
- Py_TYPE(self)->tp_free(self);
+ PepExt_TypeCallFree(self);
}
static void SbkObjectType_tp_dealloc(PyTypeObject *pyType);
@@ -70,6 +142,7 @@ void setDestroyQApplication(DestroyQAppHook func)
// PYSIDE-535: Use the C API in PyPy instead of `op->ob_dict`, directly
LIBSHIBOKEN_API PyObject *SbkObject_GetDict_NoRef(PyObject *op)
{
+ assert(Shiboken::Object::checkType(op));
#ifdef PYPY_VERSION
Shiboken::GilState state;
auto *ret = PyObject_GenericGetDict(op, nullptr);
@@ -103,20 +176,18 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam
// PYSIDE-1177: Add a setter to allow setting type doc.
static int
-type_set_doc(PyTypeObject *type, PyObject *value, void *context)
+type_set_doc(PyTypeObject *type, PyObject *value, void * /* context */)
{
if (!check_set_special_type_attr(type, value, "__doc__"))
return -1;
PyType_Modified(type);
- return PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::doc(), value);
+ Shiboken::AutoDecRef tpDict(PepType_GetDict(type));
+ return PyDict_SetItem(tpDict.object(), Shiboken::PyMagicName::doc(), value);
}
// PYSIDE-908: The function PyType_Modified does not work in PySide, so we need to
-// explicitly pass __doc__. For __signature__ it _did_ actually work, because
-// it was not existing before. We add them both for clarity.
+// explicitly pass __doc__.
static PyGetSetDef SbkObjectType_tp_getset[] = {
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(Sbk_TypeGet___signature__),
- nullptr, nullptr, nullptr},
{const_cast<char *>("__doc__"), reinterpret_cast<getter>(Sbk_TypeGet___doc__),
reinterpret_cast<setter>(type_set_doc), nullptr, nullptr},
{const_cast<char *>("__dict__"), reinterpret_cast<getter>(Sbk_TypeGet___dict__),
@@ -124,31 +195,53 @@ static PyGetSetDef SbkObjectType_tp_getset[] = {
{nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
};
-static PyType_Slot SbkObjectType_Type_slots[] = {
- {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectType_tp_dealloc)},
- {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)},
- {Py_tp_base, static_cast<void *>(&PyType_Type)},
- {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
- {Py_tp_new, reinterpret_cast<void *>(SbkObjectType_tp_new)},
- {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
- {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_tp_getset)},
- {0, nullptr}
-};
-
-// PYSIDE-535: The tp_itemsize field is inherited and does not need to be set.
-// In PyPy, it _must_ not be set, because it would have the meaning that a
-// `__len__` field must be defined. Not doing so creates a hard-to-find crash.
-static PyType_Spec SbkObjectType_Type_spec = {
- "1:Shiboken.ObjectType",
- 0,
- 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- SbkObjectType_Type_slots,
-};
+static PyTypeObject *createObjectTypeType()
+{
+ PyType_Slot SbkObjectType_Type_slots[] = {
+ {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectType_tp_dealloc)},
+ {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)},
+ {Py_tp_base, static_cast<void *>(&PyType_Type)},
+ {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
+ {Py_tp_new, reinterpret_cast<void *>(SbkObjectType_tp_new)},
+ {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
+ {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_tp_getset)},
+ {0, nullptr}
+ };
+
+ // PYSIDE-535: The tp_itemsize field is inherited and does not need to be set.
+ // In PyPy, it _must_ not be set, because it would have the meanin
+ // that a `__len__` field must be defined. Not doing so creates
+ // a hard-to-find crash.
+ //
+ // PYSIDE-2230: In Python < 3.12, the decision which base class should create
+ // the instance is arbitrarily drawn by the size of the type.
+ // Ignoring this creates a bug in the new version of bug_825 that
+ // selects the wrong metatype.
+ //
+ PyType_Spec SbkObjectType_Type_spec = {
+ "1:Shiboken.ObjectType",
+ static_cast<int>(PyType_Type.tp_basicsize) + 1, // see above
+ 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS,
+ SbkObjectType_Type_slots,
+ };
+
+ PyType_Spec SbkObjectType_Type_spec_312 = {
+ "1:Shiboken.ObjectType",
+ -long(sizeof(SbkObjectTypePrivate)),
+ 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS,
+ SbkObjectType_Type_slots,
+ };
+
+ return SbkType_FromSpec(_PepRuntimeVersion() >= 0x030C00 ?
+ &SbkObjectType_Type_spec_312 :
+ &SbkObjectType_Type_spec);
+}
PyTypeObject *SbkObjectType_TypeF(void)
{
- static auto *type = SbkType_FromSpec(&SbkObjectType_Type_spec);
+ static auto *type = createObjectTypeType();
return type;
}
@@ -185,10 +278,8 @@ static int SbkObject_tp_traverse(PyObject *self, visitproc visit, void *arg)
if (sbkSelf->ob_dict)
Py_VISIT(sbkSelf->ob_dict);
-#if PY_VERSION_HEX >= 0x03090000
// This was not needed before Python 3.9 (Python issue 35810 and 40217)
Py_VISIT(Py_TYPE(self));
-#endif
return 0;
}
@@ -208,40 +299,53 @@ static int SbkObject_tp_clear(PyObject *self)
return 0;
}
-static PyType_Slot SbkObject_Type_slots[] = {
- {Py_tp_getattro, reinterpret_cast<void *>(SbkObject_GenericGetAttr)},
- {Py_tp_setattro, reinterpret_cast<void *>(SbkObject_GenericSetAttr)},
- {Py_tp_dealloc, reinterpret_cast<void *>(SbkDeallocWrapperWithPrivateDtor)},
- {Py_tp_traverse, reinterpret_cast<void *>(SbkObject_tp_traverse)},
- {Py_tp_clear, reinterpret_cast<void *>(SbkObject_tp_clear)},
- // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)},
- {Py_tp_getset, reinterpret_cast<void *>(SbkObject_tp_getset)},
- // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)},
- {0, nullptr}
-};
-static PyType_Spec SbkObject_Type_spec = {
- "1:Shiboken.Object",
- sizeof(SbkObject),
- 0,
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
- SbkObject_Type_slots,
-};
-
-static const char *SbkObject_SignatureStrings[] = {
- "Shiboken.Object(self)",
- nullptr}; // Sentinel
+static PyTypeObject *createObjectType()
+{
+ PyType_Slot SbkObject_Type_slots[] = {
+ {Py_tp_getattro, reinterpret_cast<void *>(SbkObject_GenericGetAttr)},
+ {Py_tp_setattro, reinterpret_cast<void *>(SbkObject_GenericSetAttr)},
+ {Py_tp_dealloc, reinterpret_cast<void *>(SbkDeallocWrapperWithPrivateDtor)},
+ {Py_tp_traverse, reinterpret_cast<void *>(SbkObject_tp_traverse)},
+ {Py_tp_clear, reinterpret_cast<void *>(SbkObject_tp_clear)},
+ // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)},
+ {Py_tp_getset, reinterpret_cast<void *>(SbkObject_tp_getset)},
+ // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)},
+ {0, nullptr}
+ };
+
+ PyType_Spec SbkObject_Type_spec = {
+ "1:Shiboken.Object",
+ sizeof(SbkObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
+ SbkObject_Type_slots,
+ };
+
+ // PYSIDE-2230: When creating this type, we cannot easily handle the metaclass.
+ // In versions < Python 3.12, the metaclass can only be set
+ // indirectly by a base which has that metaclass.
+ // But before 3.12 is the minimum version, we cannot use the new
+ // function, although we would need this for 3.12 :-D
+ // We do a special patching here that is triggered through Py_None.
+ auto *type = SbkType_FromSpec_BMDWB(&SbkObject_Type_spec,
+ Py_None, // bases, spectial flag!
+ SbkObjectType_TypeF(),
+ offsetof(SbkObject, ob_dict),
+ offsetof(SbkObject, weakreflist),
+ nullptr); // bufferprocs
+ return type;
+}
PyTypeObject *SbkObject_TypeF(void)
{
- static auto *type = SbkType_FromSpec_BMDWB(&SbkObject_Type_spec,
- nullptr, // bases
- SbkObjectType_TypeF(),
- offsetof(SbkObject, ob_dict),
- offsetof(SbkObject, weakreflist),
- nullptr); // bufferprocs
+ static auto *type = createObjectType(); // bufferprocs
return type;
}
+static const char *SbkObject_SignatureStrings[] = {
+ "Shiboken.Object(self)",
+ nullptr}; // Sentinel
+
static int mainThreadDeletionHandler(void *)
{
if (Py_IsInitialized())
@@ -304,9 +408,8 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete)
if (sotp->delete_in_main_thread && Shiboken::currentThreadId() != Shiboken::mainThreadId()) {
auto &bindingManager = Shiboken::BindingManager::instance();
if (sotp->is_multicpp) {
- Shiboken::DtorAccumulatorVisitor visitor(sbkObj);
- Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
- for (const auto &e : visitor.entries())
+ const auto entries = Shiboken::getDestructorEntries(sbkObj);
+ for (const auto &e : entries)
bindingManager.addToDeletionInMainThread(e);
} else {
Shiboken::DestructorEntry e{sotp->cpp_dtor, sbkObj->d->cptr[0]};
@@ -324,10 +427,9 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete)
if (canDelete) {
if (sotp->is_multicpp) {
- Shiboken::DtorAccumulatorVisitor visitor(sbkObj);
- Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
+ const auto entries = Shiboken::getDestructorEntries(sbkObj);
Shiboken::Object::deallocData(sbkObj, true);
- callDestructor(visitor.entries());
+ callDestructor(entries);
} else {
void *cptr = sbkObj->d->cptr[0];
Shiboken::Object::deallocData(sbkObj, true);
@@ -353,6 +455,17 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete)
}
}
+static inline PyObject *_Sbk_NewVarObject(PyTypeObject *type)
+{
+ // PYSIDE-1970: Support __slots__, implemented by PyVarObject
+ auto const baseSize = sizeof(SbkObject);
+ auto varCount = Py_SIZE(type);
+ auto *self = PyObject_GC_NewVar(PyObject, type, varCount);
+ if (varCount)
+ std::memset(reinterpret_cast<char *>(self) + baseSize, 0, varCount * sizeof(void *));
+ return self;
+}
+
void SbkDeallocWrapper(PyObject *pyObj)
{
SbkDeallocWrapperCommon(pyObj, true);
@@ -376,7 +489,7 @@ void SbkObjectType_tp_dealloc(PyTypeObject *sbkType)
auto pyObj = reinterpret_cast<PyObject *>(sbkType);
PyObject_GC_UnTrack(pyObj);
-#ifndef Py_LIMITED_API
+#if !defined(Py_LIMITED_API) && !defined(PYPY_VERSION)
# if PY_VERSION_HEX >= 0x030A0000
Py_TRASHCAN_BEGIN(pyObj, 1);
# else
@@ -394,7 +507,7 @@ void SbkObjectType_tp_dealloc(PyTypeObject *sbkType)
Shiboken::Conversions::deleteConverter(sotp->converter);
PepType_SOTP_delete(sbkType);
}
-#ifndef Py_LIMITED_API
+#if !defined(Py_LIMITED_API) && !defined(PYPY_VERSION)
# if PY_VERSION_HEX >= 0x030A0000
Py_TRASHCAN_END;
# else
@@ -432,7 +545,7 @@ PyObject *MakeQAppWrapper(PyTypeObject *type)
}
// monitoring the last application state
- PyObject *qApp_curr = type != nullptr ? PyObject_GC_New(PyObject, type) : Py_None;
+ PyObject *qApp_curr = type != nullptr ? _Sbk_NewVarObject(type) : Py_None;
static PyObject *builtins = PyEval_GetBuiltins();
if (PyDict_SetItem(builtins, Shiboken::PyName::qApp(), qApp_curr) < 0)
return nullptr;
@@ -465,7 +578,7 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args
PyObject *dict;
static const char *kwlist[] = { "name", "bases", "dict", nullptr};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!O!:sbktype", const_cast<char **>(kwlist),
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO!O!:sbktype", const_cast<char **>(kwlist),
&name,
&PyTuple_Type, &pyBases,
&PyDict_Type, &dict))
@@ -473,22 +586,26 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args
for (int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) {
PyObject *baseType = PyTuple_GET_ITEM(pyBases, i);
- if (reinterpret_cast<PyTypeObject *>(baseType)->tp_new == SbkDummyNew) {
+ if (PepExt_Type_GetNewSlot(reinterpret_cast<PyTypeObject *>(baseType)) == SbkDummyNew) {
// PYSIDE-595: A base class does not allow inheritance.
return reinterpret_cast<PyTypeObject *>(SbkDummyNew(metatype, args, kwds));
}
}
- // PYSIDE-939: This is a temporary patch that circumvents the problem
- // with Py_TPFLAGS_METHOD_DESCRIPTOR until this is finally solved.
- // PyType_Ready uses mro(). We need to temporarily remove the flag from it's type.
- // We cannot use PyMethodDescr_Type since it is not exported by Python 2.7 .
- static PyTypeObject *PyMethodDescr_TypePtr = Py_TYPE(
- PyObject_GetAttr(reinterpret_cast<PyObject *>(&PyType_Type), Shiboken::PyName::mro()));
- auto hold = PyMethodDescr_TypePtr->tp_flags;
- PyMethodDescr_TypePtr->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR;
- auto *newType = PepType_Type_tp_new(metatype, args, kwds);
- PyMethodDescr_TypePtr->tp_flags = hold;
+ // PYSIDE-939: This is still a temporary patch that circumvents the problem
+ // with Py_TPFLAGS_METHOD_DESCRIPTOR. The problem exists in Python 3.8
+ // until 3.9.12, only. We check the runtime and hope for this version valishing.
+ // https://github.com/python/cpython/issues/92112 will not be fixed for 3.8 :/
+ PyTypeObject *newType{};
+ static auto triplet = _PepRuntimeVersion();
+ if (triplet >= (3 << 16 | 8 << 8 | 0) && triplet < (3 << 16 | 9 << 8 | 13)) {
+ auto hold = PyMethodDescr_Type.tp_flags;
+ PyMethodDescr_Type.tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR;
+ newType = PepType_Type_tp_new(metatype, args, kwds);
+ PyMethodDescr_Type.tp_flags = hold;
+ } else {
+ newType = PepType_Type_tp_new(metatype, args, kwds);
+ }
if (!newType)
return nullptr;
@@ -537,11 +654,11 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args
return newType;
}
-static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype)
+static PyObject *_setupNew(PyObject *obSelf, PyTypeObject *subtype)
{
auto *obSubtype = reinterpret_cast<PyObject *>(subtype);
auto *sbkSubtype = subtype;
- auto *obSelf = reinterpret_cast<PyObject *>(self);
+ auto *self = reinterpret_cast<SbkObject *>(obSelf);
Py_INCREF(obSubtype);
auto d = new SbkObjectPrivate;
@@ -565,18 +682,19 @@ static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype)
return obSelf;
}
-PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject *, PyObject *)
+PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
{
- SbkObject *self = PyObject_GC_New(SbkObject, subtype);
+ PyObject *self = _Sbk_NewVarObject(subtype);
return _setupNew(self, subtype);
}
PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *)
{
- auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype));
+ auto *obSelf = MakeQAppWrapper(subtype);
+ auto *self = reinterpret_cast<SbkObject *>(obSelf);
if (self == nullptr)
return nullptr;
- auto ret = _setupNew(self, subtype);
+ auto ret = _setupNew(obSelf, subtype);
auto priv = self->d;
priv->isQAppSingleton = 1;
return ret;
@@ -585,9 +703,9 @@ PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *)
PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
{
// PYSIDE-595: Give the same error as type_call does when tp_new is NULL.
+ const char regret[] = "¯\\_(ツ)_/¯";
PyErr_Format(PyExc_TypeError,
- "cannot create '%.100s' instances ¯\\_(ツ)_/¯",
- type->tp_name);
+ "cannot create '%.100s' instances %s", type->tp_name, regret);
return nullptr;
}
@@ -618,6 +736,12 @@ PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op)
return res;
}
+bool SbkObjectType_Check(PyTypeObject *type)
+{
+ static auto *meta = SbkObjectType_TypeF();
+ return Py_TYPE(type) == meta || PyType_IsSubtype(Py_TYPE(type), meta);
+}
+
} //extern "C"
@@ -642,52 +766,9 @@ void _destroyParentInfo(SbkObject *obj, bool keepReference)
namespace Shiboken
{
-bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor)
-{
- PyObject *bases = currentType->tp_bases;
- Py_ssize_t numBases = PyTuple_GET_SIZE(bases);
- bool result = false;
- for (int i = 0; !result && i < numBases; ++i) {
- auto type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, i));
- if (PyType_IsSubtype(type, reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) {
- result = PepType_SOTP(type)->is_user_type
- ? walkThroughClassHierarchy(type, visitor) : visitor->visit(type);
- }
- }
- return result;
-}
// Wrapper metatype and base type ----------------------------------------------------------
-HierarchyVisitor::HierarchyVisitor() = default;
-HierarchyVisitor::~HierarchyVisitor() = default;
-
-bool BaseCountVisitor::visit(PyTypeObject *)
-{
- m_count++;
- return false;
-}
-
-bool BaseAccumulatorVisitor::visit(PyTypeObject *node)
-{
- m_bases.push_back(node);
- return false;
-}
-
-bool GetIndexVisitor::visit(PyTypeObject *node)
-{
- m_index++;
- return PyType_IsSubtype(node, m_desiredType);
-}
-
-bool DtorAccumulatorVisitor::visit(PyTypeObject *node)
-{
- auto *sotp = PepType_SOTP(node);
- m_entries.push_back(DestructorEntry{sotp->cpp_dtor,
- m_pyObject->d->cptr[m_entries.size()]});
- return false;
-}
-
void _initMainThreadId(); // helper.cpp
namespace Conversions { void init(); }
@@ -705,9 +786,6 @@ void init()
//Init private data
Pep384_Init();
- if (PyType_Ready(SbkEnumType_TypeF()) < 0)
- Py_FatalError("[libshiboken] Failed to initialize Shiboken.SbkEnumType metatype.");
-
if (PyType_Ready(SbkObjectType_TypeF()) < 0)
Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapperType metatype.");
@@ -720,14 +798,20 @@ void init()
}
// PYSIDE-1415: Publish Shiboken objects.
-void initSignature(PyObject *module)
+// PYSIDE-1735: Initialize the whole Shiboken startup.
+void initShibokenSupport(PyObject *module)
{
- auto *type = SbkObject_TypeF();
- if (InitSignatureStrings(type, SbkObject_SignatureStrings) < 0)
- return;
-
Py_INCREF(SbkObject_TypeF());
PyModule_AddObject(module, "Object", reinterpret_cast<PyObject *>(SbkObject_TypeF()));
+
+ // PYSIDE-1735: When the initialization was moved into Shiboken import, this
+ // Py_INCREF became necessary. No idea why.
+ Py_INCREF(module);
+ init_shibokensupport_module();
+
+ auto *type = SbkObject_TypeF();
+ if (InitSignatureStrings(type, SbkObject_SignatureStrings) < 0)
+ Py_FatalError("Error in initShibokenSupport");
}
// setErrorAboutWrongArguments now gets overload info from the signature module.
@@ -737,6 +821,32 @@ void setErrorAboutWrongArguments(PyObject *args, const char *funcName, PyObject
SetError_Argument(args, funcName, info);
}
+PyObject *returnWrongArguments(PyObject *args, const char *funcName, PyObject *info)
+{
+ setErrorAboutWrongArguments(args, funcName, info);
+ return {};
+}
+
+int returnWrongArguments_Zero(PyObject *args, const char *funcName, PyObject *info)
+{
+ setErrorAboutWrongArguments(args, funcName, info);
+ return 0;
+}
+
+int returnWrongArguments_MinusOne(PyObject *args, const char *funcName, PyObject *info)
+{
+ setErrorAboutWrongArguments(args, funcName, info);
+ return -1;
+}
+
+PyObject *returnFromRichCompare(PyObject *result)
+{
+ if (result && !PyErr_Occurred())
+ return result;
+ Shiboken::Errors::setOperatorNotImplemented();
+ return {};
+}
+
PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, Py_ssize_t minArgs, Py_ssize_t maxArgs)
{
PyObject *result = nullptr;
@@ -754,20 +864,6 @@ PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, Py_ssize_t minArgs, Py_s
return result;
}
-class FindBaseTypeVisitor : public HierarchyVisitor
-{
-public:
- explicit FindBaseTypeVisitor(PyTypeObject *typeToFind) : m_typeToFind(typeToFind) {}
-
- bool visit(PyTypeObject *node) override
- {
- return node == m_typeToFind;
- }
-
-private:
- PyTypeObject *m_typeToFind;
-};
-
std::vector<SbkObject *> splitPyObject(PyObject *pyObj)
{
std::vector<SbkObject *> result;
@@ -808,8 +904,8 @@ bool isUserType(PyTypeObject *type)
bool canCallConstructor(PyTypeObject *myType, PyTypeObject *ctorType)
{
- FindBaseTypeVisitor visitor(ctorType);
- if (!walkThroughClassHierarchy(myType, &visitor)) {
+ auto findBasePred = [ctorType](PyTypeObject *type) { return type == ctorType; };
+ if (!walkThroughBases(myType, findBasePred)) {
PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name);
return false;
}
@@ -881,31 +977,35 @@ introduceWrapperType(PyObject *enclosingObject,
const char *originalName,
PyType_Spec *typeSpec,
ObjectDestructor cppObjDtor,
- PyTypeObject *baseType,
- PyObject *baseTypes,
+ PyObject *bases,
unsigned wrapperFlags)
{
- auto *base = baseType ? baseType : SbkObject_TypeF();
- typeSpec->slots[0].pfunc = reinterpret_cast<void *>(base);
- auto *bases = baseTypes ? baseTypes : PyTuple_Pack(1, base);
+ const auto basesSize = PySequence_Fast_GET_SIZE(bases);
+ assert(basesSize > 0);
+ typeSpec->slots[0].pfunc = PySequence_Fast_GET_ITEM(bases, 0);
auto *type = SbkType_FromSpecBasesMeta(typeSpec, bases, SbkObjectType_TypeF());
- for (int i = 0; i < PySequence_Fast_GET_SIZE(bases); ++i) {
- auto *st = reinterpret_cast<PyTypeObject *>(PySequence_Fast_GET_ITEM(bases, i));
- BindingManager::instance().addClassInheritance(st, type);
- }
-
auto sotp = PepType_SOTP(type);
if (wrapperFlags & DeleteInMainThread)
sotp->delete_in_main_thread = 1;
+ sotp->type_behaviour = (wrapperFlags & Value) != 0
+ ? BEHAVIOUR_VALUETYPE : BEHAVIOUR_OBJECTTYPE;
setOriginalName(type, originalName);
setDestructorFunction(type, cppObjDtor);
auto *ob_type = reinterpret_cast<PyObject *>(type);
- if (wrapperFlags & InnerClass)
+ if (wrapperFlags & InnerClass) {
+ // PYSIDE-2230: Instead of tp_dict, use the enclosing type.
+ // This stays interface compatible.
+ if (PyType_Check(enclosingObject)) {
+ AutoDecRef tpDict(PepType_GetDict(reinterpret_cast<PyTypeObject *>(enclosingObject)));
+ return PyDict_SetItemString(tpDict, typeName, ob_type) == 0 ? type : nullptr;
+ }
+ assert(PyDict_Check(enclosingObject));
return PyDict_SetItemString(enclosingObject, typeName, ob_type) == 0 ? type : nullptr;
+ }
// PyModule_AddObject steals type's reference.
Py_INCREF(ob_type);
@@ -920,16 +1020,19 @@ introduceWrapperType(PyObject *enclosingObject,
void setSubTypeInitHook(PyTypeObject *type, SubTypeInitHook func)
{
+ assert(SbkObjectType_Check(type));
PepType_SOTP(type)->subtype_init = func;
}
void *getTypeUserData(PyTypeObject *type)
{
+ assert(SbkObjectType_Check(type));
return PepType_SOTP(type)->user_data;
}
void setTypeUserData(PyTypeObject *type, void *userData, DeleteUserDataFunc d_func)
{
+ assert(SbkObjectType_Check(type));
auto *sotp = PepType_SOTP(type);
sotp->user_data = userData;
sotp->d_func = d_func;
@@ -952,6 +1055,26 @@ bool hasSpecialCastFunction(PyTypeObject *sbkType)
return d != nullptr && d->mi_specialcast != nullptr;
}
+// Find whether base is a direct single line base class of type
+// (no multiple inheritance), that is, a C++ pointer cast can safely be done.
+static bool isDirectAncestor(PyTypeObject *type, PyTypeObject *base)
+{
+ if (type == base)
+ return true;
+ if (PyTuple_Size(type->tp_bases) == 0)
+ return false;
+ auto *sbkObjectType = SbkObject_TypeF();
+ auto *firstBase = reinterpret_cast<PyTypeObject *>(PyTuple_GetItem(type->tp_bases, 0));
+ return firstBase != sbkObjectType
+ && PyType_IsSubtype(type, sbkObjectType) != 0
+ && isDirectAncestor(firstBase, base);
+}
+
+bool canDowncastTo(PyTypeObject *baseType, PyTypeObject *targetType)
+{
+ return isDirectAncestor(targetType, baseType);
+}
+
} // namespace ObjectType
@@ -1040,9 +1163,7 @@ void callCppDestructors(SbkObject *pyObj)
PyTypeObject *type = Py_TYPE(pyObj);
auto *sotp = PepType_SOTP(type);
if (sotp->is_multicpp) {
- Shiboken::DtorAccumulatorVisitor visitor(pyObj);
- Shiboken::walkThroughClassHierarchy(type, &visitor);
- callDestructor(visitor.entries());
+ callDestructor(getDestructorEntries(pyObj));
} else {
Shiboken::ThreadStateSaver threadSaver;
threadSaver.save();
@@ -1191,11 +1312,10 @@ void makeValid(SbkObject *self)
// If has ref to other objects make all valid again
if (self->d->referredObjects) {
- RefCountMap &refCountMap = *(self->d->referredObjects);
- RefCountMap::iterator iter;
- for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) {
- if (Shiboken::Object::checkType(it->second))
- makeValid(reinterpret_cast<SbkObject *>(it->second));
+ const RefCountMap &refCountMap = *(self->d->referredObjects);
+ for (const auto &p : refCountMap) {
+ if (Shiboken::Object::checkType(p.second))
+ makeValid(reinterpret_cast<SbkObject *>(p.second));
}
}
}
@@ -1231,7 +1351,8 @@ bool setCppPointer(SbkObject *sbkObj, PyTypeObject *desiredType, void *cptr)
const bool alreadyInitialized = sbkObj->d->cptr[idx] != nullptr;
if (alreadyInitialized)
- PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!");
+ PyErr_Format(PyExc_RuntimeError, "You can't initialize an %s object in class %s twice!",
+ desiredType->tp_name, type->tp_name);
else
sbkObj->d->cptr[idx] = cptr;
@@ -1323,20 +1444,67 @@ SbkObject *findColocatedChild(SbkObject *wrapper,
return nullptr;
}
+// Legacy, for compatibility only.
PyObject *newObject(PyTypeObject *instanceType,
void *cptr,
bool hasOwnership,
bool isExactType,
const char *typeName)
{
- // Try to find the exact type of cptr.
- if (!isExactType) {
- if (PyTypeObject *exactType = ObjectType::typeForTypeName(typeName))
- instanceType = exactType;
- else
- instanceType = BindingManager::instance().resolveType(&cptr, instanceType);
+ return isExactType
+ ? newObjectForType(instanceType, cptr, hasOwnership)
+ : newObjectWithHeuristics(instanceType, cptr, hasOwnership, typeName);
+}
+
+static PyObject *newObjectWithHeuristicsHelper(PyTypeObject *instanceType,
+ PyTypeObject *exactType,
+ void *cptr,
+ bool hasOwnership)
+{
+ // Try to find the exact type of cptr. For hierarchies with
+ // non-virtual destructors, typeid() will return the base name.
+ // Try type discovery in these cases.
+ if (exactType == nullptr || exactType == instanceType) {
+ auto resolved = BindingManager::instance().findDerivedType(cptr, instanceType);
+ if (resolved.first != nullptr
+ && Shiboken::ObjectType::canDowncastTo(instanceType, resolved.first)) {
+ exactType = resolved.first;
+ cptr = resolved.second;
+ }
}
+ return newObjectForType(exactType != nullptr ? exactType : instanceType,
+ cptr, hasOwnership);
+}
+
+PyObject *newObjectForPointer(PyTypeObject *instanceType,
+ void *cptr,
+ bool hasOwnership,
+ const char *typeName)
+{
+ // Try to find the exact type of cptr.
+ PyTypeObject *exactType = ObjectType::typeForTypeName(typeName);
+ // PYSIDE-868: In case of multiple inheritance, (for example,
+ // a function returning a QPaintDevice * from a QWidget *),
+ // use instance type to avoid pointer offset errors.
+ return exactType != nullptr && !Shiboken::ObjectType::canDowncastTo(instanceType, exactType)
+ ? newObjectForType(instanceType, cptr, hasOwnership)
+ : newObjectWithHeuristicsHelper(instanceType, exactType, cptr, hasOwnership);
+}
+
+
+PyObject *newObjectWithHeuristics(PyTypeObject *instanceType,
+ void *cptr,
+ bool hasOwnership,
+ const char *typeName)
+{
+ return newObjectWithHeuristicsHelper(instanceType,
+ ObjectType::typeForTypeName(typeName),
+ cptr, hasOwnership);
+}
+
+PyObject *newObjectForType(PyTypeObject *instanceType, void *cptr, bool hasOwnership)
+{
bool shouldCreate = true;
bool shouldRegister = true;
SbkObject *self = nullptr;
@@ -1545,7 +1713,7 @@ void deallocData(SbkObject *self, bool cleanup)
}
delete self->d; // PYSIDE-205: always delete d.
Py_XDECREF(self->ob_dict);
- Py_TYPE(self)->tp_free(self);
+ PepExt_TypeCallFree(reinterpret_cast<PyObject *>(self));
}
void setTypeUserData(SbkObject *wrapper, void *userData, DeleteUserDataFunc d_func)
@@ -1637,6 +1805,11 @@ static std::vector<PyTypeObject *> getBases(SbkObject *self)
: std::vector<PyTypeObject *>(1, Py_TYPE(self));
}
+static bool isValueType(SbkObject *self)
+{
+ return PepType_SOTP(Py_TYPE(self))->type_behaviour == BEHAVIOUR_VALUETYPE;
+}
+
void _debugFormat(std::ostream &s, SbkObject *self)
{
assert(self);
@@ -1660,6 +1833,8 @@ void _debugFormat(std::ostream &s, SbkObject *self)
s << " [validCppObject]";
if (d->cppObjectCreated)
s << " [wasCreatedByPython]";
+ s << (isValueType(self) ? " [value]" : " [object]");
+
if (d->parentInfo) {
if (auto *parent = d->parentInfo->parent)
s << ", parent=" << reinterpret_cast<PyObject *>(parent)->ob_type->tp_name
@@ -1690,8 +1865,9 @@ std::string info(SbkObject *self)
s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n"
"containsCppWrapper " << self->d->containsCppWrapper << "\n"
"validCppObject.... " << self->d->validCppObject << "\n"
- "wasCreatedByPython " << self->d->cppObjectCreated << "\n";
-
+ "wasCreatedByPython " << self->d->cppObjectCreated << "\n"
+ "value...... " << isValueType(self) << "\n"
+ "reference count... " << reinterpret_cast<PyObject *>(self)->ob_refcnt << '\n';
if (self->d->parentInfo && self->d->parentInfo->parent) {
s << "parent............ ";
@@ -1709,17 +1885,17 @@ std::string info(SbkObject *self)
}
if (self->d->referredObjects && !self->d->referredObjects->empty()) {
- Shiboken::RefCountMap &map = *self->d->referredObjects;
+ const Shiboken::RefCountMap &map = *self->d->referredObjects;
s << "referred objects.. ";
std::string lastKey;
- for (auto it = map.begin(), end = map.end(); it != end; ++it) {
- if (it->first != lastKey) {
+ for (const auto &p : map) {
+ if (p.first != lastKey) {
if (!lastKey.empty())
s << " ";
- s << '"' << it->first << "\" => ";
- lastKey = it->first;
+ s << '"' << p.first << "\" => ";
+ lastKey = p.first;
}
- Shiboken::AutoDecRef obj(PyObject_Str(it->second));
+ Shiboken::AutoDecRef obj(PyObject_Str(p.second));
s << String::toCString(obj) << ' ';
}
s << '\n';
diff --git a/sources/shiboken6/libshiboken/basewrapper.h b/sources/shiboken6/libshiboken/basewrapper.h
index 6ef3cfd30..ec5545aea 100644
--- a/sources/shiboken6/libshiboken/basewrapper.h
+++ b/sources/shiboken6/libshiboken/basewrapper.h
@@ -38,32 +38,30 @@ LIBSHIBOKEN_API void SbkDeallocQAppWrapper(PyObject *pyObj);
LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject *self);
/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance.
-typedef int *(*MultipleInheritanceInitFunction)(const void *);
+using MultipleInheritanceInitFunction = int *(*)(const void *);
/**
* Special cast function is used to correctly cast an object when it's
* part of a multiple inheritance hierarchy.
* The implementation of this function is auto generated by the generator and you don't need to care about it.
*/
-typedef void *(*SpecialCastFunction)(void *, PyTypeObject *);
-typedef PyTypeObject *(*TypeDiscoveryFunc)(void *, PyTypeObject *);
-typedef void *(*TypeDiscoveryFuncV2)(void *, PyTypeObject *);
+using SpecialCastFunction = void *(*)(void *, PyTypeObject *);
+using TypeDiscoveryFunc = PyTypeObject *(*)(void *, PyTypeObject *);
+using TypeDiscoveryFuncV2 = void *(*)(void *, PyTypeObject *);
// Used in userdata dealloc function
-typedef void (*DeleteUserDataFunc)(void *);
+using DeleteUserDataFunc = void (*)(void *);
-typedef void (*ObjectDestructor)(void *);
+using ObjectDestructor = void (*)(void *);
-typedef void (*SubTypeInitHook)(PyTypeObject *, PyObject *, PyObject *);
+using SubTypeInitHook = void (*)(PyTypeObject *, PyObject *, PyObject *);
/// PYSIDE-1019: Set the function to select the current feature.
/// Return value is the previous content.
-typedef PyObject *(*SelectableFeatureHook)(PyTypeObject *);
+using SelectableFeatureHook = void (*)(PyTypeObject *);
+using SelectableFeatureCallback = void (*)(bool);
LIBSHIBOKEN_API SelectableFeatureHook initSelectableFeature(SelectableFeatureHook func);
-
-/// PYSIDE-1019: Get access to PySide reserved bits.
-LIBSHIBOKEN_API int SbkObjectType_GetReserved(PyTypeObject *type);
-LIBSHIBOKEN_API void SbkObjectType_SetReserved(PyTypeObject *type, int value);
+LIBSHIBOKEN_API void setSelectableFeatureCallback(SelectableFeatureCallback func);
/// PYSIDE-1626: Enforcing a context switch without further action.
LIBSHIBOKEN_API void SbkObjectType_UpdateFeature(PyTypeObject *type);
@@ -72,8 +70,11 @@ LIBSHIBOKEN_API void SbkObjectType_UpdateFeature(PyTypeObject *type);
LIBSHIBOKEN_API const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type);
LIBSHIBOKEN_API void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings);
+/// PYSIDE-1735: Store the enumFlagInfo.
+LIBSHIBOKEN_API void SbkObjectType_SetEnumFlagInfo(PyTypeObject *type, const char **strings);
+
/// PYSIDE-1470: Set the function to kill a Q*Application.
-typedef void(*DestroyQAppHook)();
+using DestroyQAppHook = void(*)();
LIBSHIBOKEN_API void setDestroyQApplication(DestroyQAppHook func);
/// PYSIDE-535: Use the C API in PyPy instead of `op->ob_dict`, directly (borrowed ref)
@@ -108,6 +109,12 @@ LIBSHIBOKEN_API PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *
/// PYSIDE-74: Fallback used in all types now.
LIBSHIBOKEN_API PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op);
+/// PYSIDE-1970: Be easily able to see what is happening in the running code.
+LIBSHIBOKEN_API void disassembleFrame(const char *marker);
+
+/// PYSIDE-2230: Check if an object is an SbkObject.
+LIBSHIBOKEN_API bool SbkObjectType_Check(PyTypeObject *type);
+
} // extern "C"
namespace Shiboken
@@ -119,7 +126,7 @@ namespace Shiboken
LIBSHIBOKEN_API void init();
/// PYSIDE-1415: Publish Shiboken objects.
-LIBSHIBOKEN_API void initSignature(PyObject *module);
+LIBSHIBOKEN_API void initShibokenSupport(PyObject *module);
/// Delete the class T allocated on \p cptr.
template<typename T>
@@ -128,11 +135,25 @@ void callCppDestructor(void *cptr)
delete reinterpret_cast<T *>(cptr);
}
-// setErrorAboutWrongArguments now gets overload information from the signature module.
-// The extra info argument can contain additional data about the error.
+/// setErrorAboutWrongArguments now gets overload information from the signature module.
+/// The extra info argument can contain additional data about the error.
LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject *args, const char *funcName,
PyObject *info);
+/// Return values for the different retun variants.
+/// This is used instead of goto.
+LIBSHIBOKEN_API PyObject *returnWrongArguments(PyObject *args, const char *funcName,
+ PyObject *info);
+
+LIBSHIBOKEN_API int returnWrongArguments_Zero(PyObject *args, const char *funcName,
+ PyObject *info);
+
+LIBSHIBOKEN_API int returnWrongArguments_MinusOne(PyObject *args, const char *funcName,
+ PyObject *info);
+
+/// A simple special version for the end of rich comparison.
+LIBSHIBOKEN_API PyObject *returnFromRichCompare(PyObject *result);
+
// Return error information object if the argument count is wrong
LIBSHIBOKEN_API PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs,
Py_ssize_t minArgs,
@@ -179,14 +200,15 @@ LIBSHIBOKEN_API const char *getOriginalName(PyTypeObject *self);
LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(PyTypeObject *self, TypeDiscoveryFuncV2 func);
LIBSHIBOKEN_API void copyMultipleInheritance(PyTypeObject *self, PyTypeObject *other);
LIBSHIBOKEN_API void setMultipleInheritanceFunction(PyTypeObject *self, MultipleInheritanceInitFunction func);
-LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleInheritanceFunction(PyTypeObject *self);
+LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleInheritanceFunction(PyTypeObject *type);
LIBSHIBOKEN_API void setDestructorFunction(PyTypeObject *self, ObjectDestructor func);
enum WrapperFlags
{
InnerClass = 0x1,
- DeleteInMainThread = 0x2
+ DeleteInMainThread = 0x2,
+ Value = 0x4
};
/**
@@ -207,13 +229,12 @@ enum WrapperFlags
* \returns true if the initialization went fine, false otherwise.
*/
LIBSHIBOKEN_API PyTypeObject *introduceWrapperType(PyObject *enclosingObject,
- const char *typeName,
- const char *originalName,
- PyType_Spec *typeSpec,
- ObjectDestructor cppObjDtor,
- PyTypeObject *baseType,
- PyObject *baseTypes,
- unsigned wrapperFlags = 0);
+ const char *typeName,
+ const char *originalName,
+ PyType_Spec *typeSpec,
+ ObjectDestructor cppObjDtor,
+ PyObject *bases,
+ unsigned wrapperFlags = 0);
/**
* Set the subtype init hook for a type.
@@ -244,6 +265,14 @@ LIBSHIBOKEN_API PyTypeObject *typeForTypeName(const char *typeName);
* \since 5.12
*/
LIBSHIBOKEN_API bool hasSpecialCastFunction(PyTypeObject *sbkType);
+
+/// Returns whether a C++ pointer of \p baseType can be safely downcast
+/// to \p targetType (base is a direct, single line base class of targetType).
+/// (is a direct, single-line inheritance)
+/// \param baseType Python type of base class
+/// \param targetType Python type of derived class
+/// \since 6.8
+LIBSHIBOKEN_API bool canDowncastTo(PyTypeObject *baseType, PyTypeObject *targetType);
}
namespace Object {
@@ -276,7 +305,8 @@ LIBSHIBOKEN_API SbkObject *findColocatedChild(SbkObject *wrapper,
const PyTypeObject *instanceType);
/**
- * Bind a C++ object to Python.
+ * Bind a C++ object to Python. Forwards to
+ * newObjectWithHeuristics(), newObjectForType() depending on \p isExactType.
* \param instanceType equivalent Python type for the C++ object.
* \param hasOwnership if true, Python will try to delete the underlying C++ object when there's no more refs.
* \param isExactType if false, Shiboken will use some heuristics to detect the correct Python type of this C++
@@ -290,6 +320,40 @@ LIBSHIBOKEN_API PyObject *newObject(PyTypeObject *instanceType,
bool isExactType = false,
const char *typeName = nullptr);
+/// Bind a C++ object to Python for polymorphic pointers. Calls
+/// newObjectWithHeuristics() with an additional check for multiple
+/// inheritance, in which case it will fall back to instanceType.
+/// \param instanceType Equivalent Python type for the C++ object.
+/// \param hasOwnership if true, Python will try to delete the underlying C++ object
+/// when there's no more refs.
+/// \param typeName If non-null, this will be used as helper to find the correct
+/// Python type for this object (obtained by typeid().name().
+LIBSHIBOKEN_API PyObject *newObjectForPointer(PyTypeObject *instanceType,
+ void *cptr,
+ bool hasOwnership = true,
+ const char *typeName = nullptr);
+
+/// Bind a C++ object to Python using some heuristics to detect the correct
+/// Python type of this C++ object. In any case \p instanceType must be provided;
+/// it'll be used as search starting point and as fallback.
+/// \param instanceType Equivalent Python type for the C++ object.
+/// \param hasOwnership if true, Python will try to delete the underlying C++ object
+/// C++ object when there are no more references.
+/// when there's no more refs.
+/// \param typeName If non-null, this will be used as helper to find the correct
+/// Python type for this object (obtained by typeid().name().
+LIBSHIBOKEN_API PyObject *newObjectWithHeuristics(PyTypeObject *instanceType,
+ void *cptr,
+ bool hasOwnership = true,
+ const char *typeName = nullptr);
+
+/// Bind a C++ object to Python using the given type.
+/// \param instanceType Equivalent Python type for the C++ object.
+/// \param hasOwnership if true, Python will try to delete the underlying
+/// C++ object when there are no more references.
+LIBSHIBOKEN_API PyObject *newObjectForType(PyTypeObject *instanceType,
+ void *cptr, bool hasOwnership = true);
+
/**
* Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it.
*/
diff --git a/sources/shiboken6/libshiboken/basewrapper_p.h b/sources/shiboken6/libshiboken/basewrapper_p.h
index 775b9bd5c..fb9140793 100644
--- a/sources/shiboken6/libshiboken/basewrapper_p.h
+++ b/sources/shiboken6/libshiboken/basewrapper_p.h
@@ -30,14 +30,12 @@ using ChildrenList = std::set<SbkObject *>;
/// Structure used to store information about object parent and children.
struct ParentInfo
{
- /// Default ctor.
- ParentInfo() : parent(nullptr), hasWrapperRef(false) {}
/// Pointer to parent object.
- SbkObject *parent;
+ SbkObject *parent = nullptr;
/// List of object children.
ChildrenList children;
/// has internal ref
- bool hasWrapperRef;
+ bool hasWrapperRef = false;
};
} // namespace Shiboken
@@ -51,6 +49,12 @@ extern "C"
*/
struct SbkObjectPrivate
{
+ SbkObjectPrivate() noexcept = default;
+ SbkObjectPrivate(const SbkObjectPrivate &) = delete;
+ SbkObjectPrivate(SbkObjectPrivate &&o) = delete;
+ SbkObjectPrivate &operator=(const SbkObjectPrivate &) = delete;
+ SbkObjectPrivate &operator=(SbkObjectPrivate &&o) = delete;
+
/// Pointer to the C++ class.
void ** cptr;
/// True when Python is responsible for freeing the used memory.
@@ -97,15 +101,6 @@ struct SbkObjectTypePrivate
TypeDiscoveryFuncV2 type_discovery;
/// Pointer to a function responsible for deletion of the C++ instance calling the proper destructor.
ObjectDestructor cpp_dtor;
- /// PYSIDE-1019: Caching the current select Id
- unsigned int pyside_reserved_bits : 8; // MSVC has bug with the sign bit!
- /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes.
- unsigned int is_multicpp : 1;
- /// True if this type was defined by the user.
- unsigned int is_user_type : 1;
- /// Tells is the type is a value type or an object-type, see BEHAVIOUR_ *constants.
- unsigned int type_behaviour : 2;
- unsigned int delete_in_main_thread : 1;
/// C++ name
char *original_name;
/// Type user data
@@ -113,6 +108,18 @@ struct SbkObjectTypePrivate
DeleteUserDataFunc d_func;
void (*subtype_init)(PyTypeObject *, PyObject *, PyObject *);
const char **propertyStrings;
+ const char **enumFlagInfo;
+ PyObject *enumFlagsDict;
+ PyObject *enumTypeDict;
+
+ /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes.
+ unsigned int is_multicpp : 1;
+ /// True if this type was defined by the user (a class written in Python inheriting
+ /// a class provided by a Shiboken binding).
+ unsigned int is_user_type : 1;
+ /// Tells is the type is a value type or an object-type, see BEHAVIOUR_ *constants.
+ unsigned int type_behaviour : 2;
+ unsigned int delete_in_main_thread : 1;
};
@@ -136,107 +143,7 @@ struct DestructorEntry
**/
std::vector<SbkObject *> splitPyObject(PyObject *pyObj);
-/**
-* Visitor class used by walkOnClassHierarchy function.
-*/
-class HierarchyVisitor
-{
-public:
- HierarchyVisitor(const HierarchyVisitor &) = delete;
- HierarchyVisitor(HierarchyVisitor &&) = delete;
- HierarchyVisitor &operator=(const HierarchyVisitor &) = delete;
- HierarchyVisitor &operator=(HierarchyVisitor &&) = delete;
-
- HierarchyVisitor();
- virtual ~HierarchyVisitor();
-
- virtual bool visit(PyTypeObject *node) = 0; // return true to terminate
-};
-
-class BaseCountVisitor : public HierarchyVisitor
-{
-public:
- bool visit(PyTypeObject *) override;
-
- int count() const { return m_count; }
-
-private:
- int m_count = 0;
-};
-
-class BaseAccumulatorVisitor : public HierarchyVisitor
-{
-public:
- using Result = std::vector<PyTypeObject *>;
-
- bool visit(PyTypeObject *node) override;
-
- Result bases() const { return m_bases; }
-
-private:
- Result m_bases;
-};
-
-class GetIndexVisitor : public HierarchyVisitor
-{
-public:
- explicit GetIndexVisitor(PyTypeObject *desiredType) : m_desiredType(desiredType) {}
-
- bool visit(PyTypeObject *node) override;
-
- int index() const { return m_index; }
-
-private:
- int m_index = -1;
- PyTypeObject *m_desiredType;
-};
-
-/// Collect destructors and C++ instances of each C++ object held by a Python
-/// object
-class DtorAccumulatorVisitor : public HierarchyVisitor
-{
-public:
- explicit DtorAccumulatorVisitor(SbkObject *pyObj) : m_pyObject(pyObj) {}
-
- bool visit(PyTypeObject *node) override;
-
- using DestructorEntries = std::vector<DestructorEntry>;
-
- const DestructorEntries &entries() const { return m_entries; }
-
-private:
- DestructorEntries m_entries;
- SbkObject *m_pyObject;
-};
-
-/// \internal Internal function used to walk on classes inheritance trees.
-/**
-* Walk on class hierarchy using a DFS algorithm.
-* For each pure Shiboken type found, HierarchyVisitor::visit is called and the algorithm
-* considers all children of this type as visited.
-*/
-bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor);
-
-inline int getTypeIndexOnHierarchy(PyTypeObject *baseType, PyTypeObject *desiredType)
-{
- GetIndexVisitor visitor(desiredType);
- walkThroughClassHierarchy(baseType, &visitor);
- return visitor.index();
-}
-
-inline int getNumberOfCppBaseClasses(PyTypeObject *baseType)
-{
- BaseCountVisitor visitor;
- walkThroughClassHierarchy(baseType, &visitor);
- return visitor.count();
-}
-
-inline std::vector<PyTypeObject *> getCppBaseClasses(PyTypeObject *baseType)
-{
- BaseAccumulatorVisitor visitor;
- walkThroughClassHierarchy(baseType, &visitor);
- return visitor.bases();
-}
+int getNumberOfCppBaseClasses(PyTypeObject *baseType);
namespace Object
{
diff --git a/sources/shiboken6/libshiboken/bindingmanager.cpp b/sources/shiboken6/libshiboken/bindingmanager.cpp
index 9d74e9721..83c927ae5 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken6/libshiboken/bindingmanager.cpp
@@ -6,101 +6,162 @@
#include "basewrapper_p.h"
#include "bindingmanager.h"
#include "gilstate.h"
+#include "helper.h"
+#include "sbkmodule.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkfeature_base.h"
#include "debugfreehook.h"
#include <cstddef>
+#include <cstring>
#include <fstream>
+#include <iostream>
#include <mutex>
+#include <string_view>
#include <unordered_map>
+#include <unordered_set>
+
+// GraphNode for the dependency graph. It keeps a pointer to
+// the TypeInitStruct to be able to lazily create the type and hashes
+// by the full type name.
+struct GraphNode
+{
+ explicit GraphNode(Shiboken::Module::TypeInitStruct *i) : name(i->fullName), initStruct(i) {}
+ explicit GraphNode(const char *n) : name(n), initStruct(nullptr) {} // Only for searching
+
+ std::string_view name;
+ Shiboken::Module::TypeInitStruct *initStruct;
+
+ friend bool operator==(const GraphNode &n1, const GraphNode &n2) { return n1.name == n2.name; }
+ friend bool operator!=(const GraphNode &n1, const GraphNode &n2) { return n1.name != n2.name; }
+};
+
+template <>
+struct std::hash<GraphNode> {
+ size_t operator()(const GraphNode &n) const noexcept
+ {
+ return std::hash<std::string_view>{}(n.name);
+ }
+};
namespace Shiboken
{
using WrapperMap = std::unordered_map<const void *, SbkObject *>;
-class Graph
+template <class NodeType>
+class BaseGraph
{
public:
- using NodeList = std::vector<PyTypeObject *>;
- using Edges = std::unordered_map<PyTypeObject *, NodeList>;
+ using NodeList = std::vector<NodeType>;
+ using NodeSet = std::unordered_set<NodeType>;
+
+ using Edges = std::unordered_map<NodeType, NodeList>;
Edges m_edges;
- Graph() = default;
+ BaseGraph() = default;
- void addEdge(PyTypeObject *from, PyTypeObject *to)
+ void addEdge(NodeType from, NodeType to)
{
m_edges[from].push_back(to);
}
-#ifndef NDEBUG
- void dumpDotGraph()
+ NodeSet nodeSet() const
{
- std::ofstream file("/tmp/shiboken_graph.dot");
-
- file << "digraph D {\n";
-
- for (auto i = m_edges.begin(), end = m_edges.end(); i != end; ++i) {
- auto *node1 = i->first;
- const NodeList &nodeList = i->second;
- for (const PyTypeObject *o : nodeList) {
- auto *node2 = o;
- file << '"' << node2->tp_name << "\" -> \""
- << node1->tp_name << "\"\n";
- }
+ NodeSet result;
+ for (const auto &p : m_edges) {
+ result.insert(p.first);
+ for (const auto node2 : p.second)
+ result.insert(node2);
}
- file << "}\n";
+ return result;
}
-#endif
+};
+
+class Graph : public BaseGraph<GraphNode>
+{
+public:
+ using TypeCptrPair = BindingManager::TypeCptrPair;
- PyTypeObject *identifyType(void **cptr, PyTypeObject *type, PyTypeObject *baseType) const
+ TypeCptrPair identifyType(void *cptr, PyTypeObject *type, PyTypeObject *baseType) const
{
- auto edgesIt = m_edges.find(type);
- if (edgesIt != m_edges.end()) {
- const NodeList &adjNodes = m_edges.find(type)->second;
- for (PyTypeObject *node : adjNodes) {
- PyTypeObject *newType = identifyType(cptr, node, baseType);
- if (newType)
- return newType;
- }
- }
- void *typeFound = nullptr;
- auto *sotp = PepType_SOTP(type);
- if (sotp->type_discovery)
- typeFound = sotp->type_discovery(*cptr, baseType);
- if (typeFound) {
- // This "typeFound != type" is needed for backwards compatibility with old modules using a newer version of
- // libshiboken because old versions of type_discovery function used to return a PyTypeObject *instead of
- // a possible variation of the C++ instance pointer (*cptr).
- if (typeFound != type)
- *cptr = typeFound;
- return type;
- }
- return nullptr;
+ return identifyType(cptr, GraphNode(type->tp_name), type, baseType);
}
-};
+ bool dumpTypeGraph(const char *fileName) const;
-#ifndef NDEBUG
-static void showWrapperMap(const WrapperMap &wrapperMap)
+private:
+ TypeCptrPair identifyType(void *cptr, const GraphNode &typeNode, PyTypeObject *type,
+ PyTypeObject *baseType) const;
+};
+
+Graph::TypeCptrPair Graph::identifyType(void *cptr,
+ const GraphNode &typeNode, PyTypeObject *type,
+ PyTypeObject *baseType) const
{
- if (Py_VerboseFlag > 0) {
- fprintf(stderr, "-------------------------------\n");
- fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size());
- for (auto it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) {
- const SbkObject *sbkObj = it->second;
- fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", it->first,
- static_cast<const void *>(sbkObj),
- (Py_TYPE(sbkObj))->tp_name,
- int(reinterpret_cast<const PyObject *>(sbkObj)->ob_refcnt));
+ assert(typeNode.initStruct != nullptr || type != nullptr);
+ auto edgesIt = m_edges.find(typeNode);
+ if (edgesIt != m_edges.end()) {
+ const NodeList &adjNodes = edgesIt->second;
+ for (const auto &node : adjNodes) {
+ auto newType = identifyType(cptr, node, nullptr, baseType);
+ if (newType.first != nullptr)
+ return newType;
}
- fprintf(stderr, "-------------------------------\n");
}
+
+ if (type == nullptr) {
+ if (typeNode.initStruct->type == nullptr) // Layzily create type
+ type = Shiboken::Module::get(*typeNode.initStruct);
+ else
+ type = typeNode.initStruct->type;
+ }
+
+ auto *sotp = PepType_SOTP(type);
+ if (sotp->type_discovery != nullptr) {
+ if (void *derivedCPtr = sotp->type_discovery(cptr, baseType))
+ return {type, derivedCPtr};
+ }
+ return {nullptr, nullptr};
+}
+
+static void formatDotNode(std::string_view name, std::ostream &file)
+{
+ auto lastDot = name.rfind('.');
+ file << " \"" << name << "\" [ label=";
+ if (lastDot != std::string::npos) {
+ file << '"' << name.substr(lastDot + 1) << "\" tooltip=\""
+ << name.substr(0, lastDot) << '"';
+ } else {
+ file << '"' << name << '"';
+ }
+ file << " ]\n";
+}
+
+bool Graph::dumpTypeGraph(const char *fileName) const
+{
+ std::ofstream file(fileName);
+ if (!file.good())
+ return false;
+
+ file << "digraph D {\n";
+
+ // Define nodes with short names
+ for (const auto &node : nodeSet())
+ formatDotNode(node.name, file);
+
+ // Write edges
+ for (const auto &p : m_edges) {
+ const auto &node1 = p.first;
+ const NodeList &nodeList = p.second;
+ for (const auto &node2 : nodeList)
+ file << " \"" << node2.name << "\" -> \"" << node1.name << "\"\n";
+ }
+ file << "}\n";
+ return true;
}
-#endif
struct BindingManager::BindingManagerPrivate {
using DestructorEntries = std::vector<DestructorEntry>;
@@ -113,20 +174,19 @@ struct BindingManager::BindingManagerPrivate {
std::recursive_mutex wrapperMapLock;
Graph classHierarchy;
DestructorEntries deleteInMainThread;
- bool destroying;
- BindingManagerPrivate() : destroying(false) {}
- bool releaseWrapper(void *cptr, SbkObject *wrapper);
- void assignWrapper(SbkObject *wrapper, const void *cptr);
+ bool releaseWrapper(void *cptr, SbkObject *wrapper, const int *bases = nullptr);
+ bool releaseWrapperHelper(void *cptr, SbkObject *wrapper);
+ void assignWrapper(SbkObject *wrapper, const void *cptr, const int *bases = nullptr);
+ void assignWrapperHelper(SbkObject *wrapper, const void *cptr);
};
-bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject *wrapper)
+inline bool BindingManager::BindingManagerPrivate::releaseWrapperHelper(void *cptr, SbkObject *wrapper)
{
// The wrapper argument is checked to ensure that the correct wrapper is released.
// Returns true if the correct wrapper is found and released.
// If wrapper argument is NULL, no such check is performed.
- std::lock_guard<std::recursive_mutex> guard(wrapperMapLock);
auto iter = wrapperMapper.find(cptr);
if (iter != wrapperMapper.end() && (wrapper == nullptr || iter->second == wrapper)) {
wrapperMapper.erase(iter);
@@ -135,15 +195,41 @@ bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject
return false;
}
-void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr)
+bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject *wrapper,
+ const int *bases)
{
assert(cptr);
std::lock_guard<std::recursive_mutex> guard(wrapperMapLock);
+ const bool result = releaseWrapperHelper(cptr, wrapper);
+ if (bases != nullptr) {
+ auto *base = static_cast<uint8_t *>(cptr);
+ for (const auto *offset = bases; *offset != -1; ++offset)
+ releaseWrapperHelper(base + *offset, wrapper);
+ }
+ return result;
+}
+
+inline void BindingManager::BindingManagerPrivate::assignWrapperHelper(SbkObject *wrapper,
+ const void *cptr)
+{
auto iter = wrapperMapper.find(cptr);
if (iter == wrapperMapper.end())
wrapperMapper.insert(std::make_pair(cptr, wrapper));
}
+void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr,
+ const int *bases)
+{
+ assert(cptr);
+ std::lock_guard<std::recursive_mutex> guard(wrapperMapLock);
+ assignWrapperHelper(wrapper, cptr);
+ if (bases != nullptr) {
+ const auto *base = static_cast<const uint8_t *>(cptr);
+ for (const auto *offset = bases; *offset != -1; ++offset)
+ assignWrapperHelper(wrapper, base + *offset);
+ }
+}
+
BindingManager::BindingManager()
{
m_d = new BindingManager::BindingManagerPrivate;
@@ -159,7 +245,8 @@ BindingManager::~BindingManager()
debugRemoveFreeHook();
#endif
#ifndef NDEBUG
- showWrapperMap(m_d->wrapperMapper);
+ if (Shiboken::pyVerbose() > 0)
+ dumpWrapperMap();
#endif
/* Cleanup hanging references. We just invalidate them as when
* the BindingManager is being destroyed the interpreter is alredy
@@ -195,15 +282,7 @@ void BindingManager::registerWrapper(SbkObject *pyObj, void *cptr)
if (d->mi_init && !d->mi_offsets)
d->mi_offsets = d->mi_init(cptr);
- m_d->assignWrapper(pyObj, cptr);
- if (d->mi_offsets) {
- int *offset = d->mi_offsets;
- while (*offset != -1) {
- if (*offset > 0)
- m_d->assignWrapper(pyObj, reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset));
- offset++;
- }
- }
+ m_d->assignWrapper(pyObj, cptr, d->mi_offsets);
}
void BindingManager::releaseWrapper(SbkObject *sbkObj)
@@ -213,17 +292,10 @@ void BindingManager::releaseWrapper(SbkObject *sbkObj)
int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1);
void ** cptrs = reinterpret_cast<SbkObject *>(sbkObj)->d->cptr;
+ const int *mi_offsets = d != nullptr ? d->mi_offsets : nullptr;
for (int i = 0; i < numBases; ++i) {
- auto *cptr = reinterpret_cast<unsigned char *>(cptrs[i]);
- m_d->releaseWrapper(cptr, sbkObj);
- if (d && d->mi_offsets) {
- int *offset = d->mi_offsets;
- while (*offset != -1) {
- if (*offset > 0)
- m_d->releaseWrapper(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset), sbkObj);
- offset++;
- }
- }
+ if (cptrs[i] != nullptr)
+ m_d->releaseWrapper(cptrs[i], sbkObj, mi_offsets);
}
sbkObj->d->validCppObject = false;
}
@@ -256,7 +328,7 @@ PyObject *BindingManager::getOverride(const void *cptr,
SbkObject *wrapper = retrieveWrapper(cptr);
// The refcount can be 0 if the object is dieing and someone called
// a virtual method from the destructor
- if (!wrapper || reinterpret_cast<const PyObject *>(wrapper)->ob_refcnt == 0)
+ if (!wrapper || Py_REFCNT(reinterpret_cast<const PyObject *>(wrapper)) == 0)
return nullptr;
// PYSIDE-1626: Touch the type to initiate switching early.
@@ -276,6 +348,8 @@ PyObject *BindingManager::getOverride(const void *cptr,
auto *obWrapper = reinterpret_cast<PyObject *>(wrapper);
auto *wrapper_dict = SbkObject_GetDict_NoRef(obWrapper);
if (PyObject *method = PyDict_GetItem(wrapper_dict, pyMethodName)) {
+ // Note: This special case was implemented for duck-punching, which happens
+ // in the instance dict. It does not work with properties.
Py_INCREF(method);
return method;
}
@@ -317,36 +391,53 @@ PyObject *BindingManager::getOverride(const void *cptr,
}
if (method != nullptr) {
- PyObject *defaultMethod;
+ PyObject *defaultMethod{};
PyObject *mro = Py_TYPE(wrapper)->tp_mro;
int size = PyTuple_GET_SIZE(mro);
+ bool defaultFound = false;
// The first class in the mro (index 0) is the class being checked and it should not be tested.
// The last class in the mro (size - 1) is the base Python object class which should not be tested also.
for (int idx = 1; idx < size - 1; ++idx) {
auto *parent = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
- if (parent->tp_dict) {
- defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName);
- if (defaultMethod && function != defaultMethod)
- return method;
+ AutoDecRef tpDict(PepType_GetDict(parent));
+ auto *parentDict = tpDict.object();
+ if (parentDict) {
+ defaultMethod = PyDict_GetItem(parentDict, pyMethodName);
+ if (defaultMethod) {
+ defaultFound = true;
+ if (function != defaultMethod)
+ return method;
+ }
}
}
-
+ // PYSIDE-2255: If no default method was found, use the method.
+ if (!defaultFound)
+ return method;
Py_DECREF(method);
}
return nullptr;
}
-void BindingManager::addClassInheritance(PyTypeObject *parent, PyTypeObject *child)
+void BindingManager::addClassInheritance(Module::TypeInitStruct *parent,
+ Module::TypeInitStruct *child)
{
- m_d->classHierarchy.addEdge(parent, child);
+ m_d->classHierarchy.addEdge(GraphNode(parent), GraphNode(child));
}
+BindingManager::TypeCptrPair BindingManager::findDerivedType(void *cptr, PyTypeObject *type) const
+{
+ return m_d->classHierarchy.identifyType(cptr, type, type);
+}
+
+// FIXME PYSIDE7: remove, just for compatibility
PyTypeObject *BindingManager::resolveType(void **cptr, PyTypeObject *type)
{
- PyTypeObject *identifiedType = m_d->classHierarchy.identifyType(cptr, type, type);
- return identifiedType ? identifiedType : type;
+ auto result = findDerivedType(*cptr, type);
+ if (result.second != nullptr)
+ *cptr = result.second;
+ return result.first != nullptr ? result.first : type;
}
std::set<PyObject *> BindingManager::getAllPyObjects()
@@ -364,10 +455,94 @@ std::set<PyObject *> BindingManager::getAllPyObjects()
void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void *data)
{
WrapperMap copy = m_d->wrapperMapper;
- for (auto it = copy.begin(); it != copy.end(); ++it) {
- if (hasWrapper(it->first))
- visitor(it->second, data);
+ for (const auto &p : copy) {
+ if (hasWrapper(p.first))
+ visitor(p.second, data);
+ }
+}
+
+bool BindingManager::dumpTypeGraph(const char *fileName) const
+{
+ return m_d->classHierarchy.dumpTypeGraph(fileName);
+}
+
+void BindingManager::dumpWrapperMap()
+{
+ const auto &wrapperMap = m_d->wrapperMapper;
+ std::cerr << "-------------------------------\n"
+ << "WrapperMap size: " << wrapperMap.size() << " Types: "
+ << m_d->classHierarchy.nodeSet().size() << '\n';
+ for (auto it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) {
+ const SbkObject *sbkObj = it->second;
+ std::cerr << "key: " << it->first << ", value: "
+ << static_cast<const void *>(sbkObj) << " ("
+ << (Py_TYPE(sbkObj))->tp_name << ", refcnt: "
+ << Py_REFCNT(reinterpret_cast<const PyObject *>(sbkObj)) << ")\n";
+ }
+ std::cerr << "-------------------------------\n";
+}
+
+static bool isPythonType(PyTypeObject *type)
+{
+ // This is a type which should be called by multiple inheritance.
+ // It is either a pure Python type or a derived PySide type.
+ return !ObjectType::checkType(type) || ObjectType::isUserType(type);
+}
+
+bool callInheritedInit(PyObject *self, PyObject *args, PyObject *kwds,
+ const char *fullName)
+{
+ using Shiboken::AutoDecRef;
+
+ static PyObject *const _init = String::createStaticString("__init__");
+ static PyObject *objectInit =
+ PyObject_GetAttr(reinterpret_cast<PyObject *>(&PyBaseObject_Type), _init);
+
+ // A native C++ self cannot have multiple inheritance.
+ if (!Object::isUserType(self))
+ return false;
+
+ auto *startType = Py_TYPE(self);
+ auto *mro = startType->tp_mro;
+ Py_ssize_t idx, n = PyTuple_GET_SIZE(mro);
+ auto classNameLen = std::strrchr(fullName, '.') - fullName;
+ /* No need to check the last one: it's gonna be skipped anyway. */
+ for (idx = 0; idx + 1 < n; ++idx) {
+ auto *lookType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
+ const char *lookName = lookType->tp_name;
+ auto lookLen = long(std::strlen(lookName));
+ if (std::strncmp(lookName, fullName, classNameLen) == 0 && lookLen == classNameLen)
+ break;
+ }
+ // We are now at the first non-Python class `QObject`.
+ // mro: ('C', 'A', 'QObject', 'Object', 'B', 'object')
+ // We want to catch class `B` and call its `__init__`.
+ for (idx += 1; idx + 1 < n; ++idx) {
+ auto *t = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
+ if (isPythonType(t))
+ break;
}
+ if (idx >= n)
+ return false;
+
+ auto *obSubType = PyTuple_GET_ITEM(mro, idx);
+ auto *subType = reinterpret_cast<PyTypeObject *>(obSubType);
+ if (subType == &PyBaseObject_Type)
+ return false;
+ AutoDecRef func(PyObject_GetAttr(obSubType, _init));
+ // PYSIDE-2654: If this has no implementation then we get object.__init__
+ // but that is the same case like above.
+ if (func == objectInit)
+ return false;
+ // PYSIDE-2294: We need to explicitly ignore positional args in a mixin class.
+ SBK_UNUSED(args);
+ AutoDecRef newArgs(PyTuple_New(1));
+ auto *newArgsOb = newArgs.object();
+ Py_INCREF(self);
+ PyTuple_SET_ITEM(newArgsOb, 0, self);
+ // Note: This can fail, so please always check the error status.
+ AutoDecRef result(PyObject_Call(func, newArgs, kwds));
+ return true;
}
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/bindingmanager.h b/sources/shiboken6/libshiboken/bindingmanager.h
index e299dad96..54c4e486a 100644
--- a/sources/shiboken6/libshiboken/bindingmanager.h
+++ b/sources/shiboken6/libshiboken/bindingmanager.h
@@ -5,17 +5,23 @@
#define BINDINGMANAGER_H
#include "sbkpython.h"
-#include <set>
#include "shibokenmacros.h"
+#include <set>
+#include <utility>
+
struct SbkObject;
namespace Shiboken
{
+namespace Module {
+struct TypeInitStruct;
+}
+
struct DestructorEntry;
-typedef void (*ObjectVisitor)(SbkObject *, void *);
+using ObjectVisitor = void (*)(SbkObject *, void *);
class LIBSHIBOKEN_API BindingManager
{
@@ -38,7 +44,15 @@ public:
SbkObject *retrieveWrapper(const void *cptr);
PyObject *getOverride(const void *cptr, PyObject *nameCache[], const char *methodName);
- void addClassInheritance(PyTypeObject *parent, PyTypeObject *child);
+ void addClassInheritance(Module::TypeInitStruct *parent, Module::TypeInitStruct *child);
+ /// Try to find the correct type of cptr via type discovery knowing that it's at least
+ /// of type \p type. If a derived class is found, it returns a cptr cast to the type
+ /// (which may be different in case of multiple inheritance.
+ /// \param cptr a pointer to the instance of type \p type
+ /// \param type type of cptr
+ using TypeCptrPair = std::pair<PyTypeObject *, void *>;
+ TypeCptrPair findDerivedType(void *cptr, PyTypeObject *type) const;
+
/**
* Try to find the correct type of *cptr knowing that it's at least of type \p type.
* In case of multiple inheritance this function may change the contents of cptr.
@@ -46,7 +60,7 @@ public:
* \param type type of *cptr
* \warning This function is slow, use it only as last resort.
*/
- PyTypeObject *resolveType(void **cptr, PyTypeObject *type);
+ [[deprecated]] PyTypeObject *resolveType(void **cptr, PyTypeObject *type);
std::set<PyObject *> getAllPyObjects();
@@ -59,6 +73,9 @@ public:
*/
void visitAllPyObjects(ObjectVisitor visitor, void *data);
+ bool dumpTypeGraph(const char *fileName) const;
+ void dumpWrapperMap();
+
private:
~BindingManager();
BindingManager();
@@ -67,6 +84,9 @@ private:
BindingManagerPrivate *m_d;
};
+LIBSHIBOKEN_API bool callInheritedInit(PyObject *self, PyObject *args, PyObject *kwds,
+ const char *fullName);
+
} // namespace Shiboken
#endif // BINDINGMANAGER_H
diff --git a/sources/shiboken6/libshiboken/bufferprocs_py37.h b/sources/shiboken6/libshiboken/bufferprocs_py37.h
index 06b42cabd..e16194e50 100644
--- a/sources/shiboken6/libshiboken/bufferprocs_py37.h
+++ b/sources/shiboken6/libshiboken/bufferprocs_py37.h
@@ -67,8 +67,8 @@ typedef struct bufferinfo {
void *internal;
} Pep_buffer;
-typedef int (*getbufferproc)(PyObject *, Pep_buffer *, int);
-typedef void (*releasebufferproc)(PyObject *, Pep_buffer *);
+using getbufferproc =int (*)(PyObject *, Pep_buffer *, int);
+using releasebufferproc = void (*)(PyObject *, Pep_buffer *);
/* Maximum number of dimensions */
#define PyBUF_MAX_NDIM 64
diff --git a/sources/shiboken6/libshiboken/debugfreehook.cpp b/sources/shiboken6/libshiboken/debugfreehook.cpp
index 1a80a2514..13df6bd6c 100644
--- a/sources/shiboken6/libshiboken/debugfreehook.cpp
+++ b/sources/shiboken6/libshiboken/debugfreehook.cpp
@@ -6,8 +6,8 @@
#include "gilstate.h"
#if defined(_WIN32) && defined(_DEBUG)
-#include <crtdbg.h>
-#include <windows.h>
+# include <sbkwindows.h>
+# include <crtdbg.h>
#endif
#ifdef __GLIBC__
diff --git a/sources/shiboken6/libshiboken/embed/embedding_generator.py b/sources/shiboken6/libshiboken/embed/embedding_generator.py
index 96f66b949..a058fd372 100644
--- a/sources/shiboken6/libshiboken/embed/embedding_generator.py
+++ b/sources/shiboken6/libshiboken/embed/embedding_generator.py
@@ -122,22 +122,23 @@ def _embed_file(fin, fout):
limit = 50
text = fin.readlines()
print(textwrap.dedent("""
- /*
- * This is a ZIP archive of all Python files in the directory
- * "shiboken6/shibokenmodule/files.dir/shibokensupport/signature"
- * There is also a toplevel file "signature_bootstrap.py[c]" that will be
- * directly executed from C++ as a bootstrap loader.
- */
+ // This is a ZIP archive of all Python files in the directory
+ // "shiboken6/shibokenmodule/files.dir/shibokensupport/signature"
+ // There is also a toplevel file "signature_bootstrap.py[c]" that will be
+ // directly executed from C++ as a bootstrap loader.
""").strip(), file=fout)
block, blocks = 0, len(text) // limit + 1
for idx, line in enumerate(text):
if idx % limit == 0:
+ if block:
+ fout.write(')"\n')
comma = "," if block else ""
block += 1
- print(file=fout)
- print(f'/* Block {block} of {blocks} */{comma}', file=fout)
- print(f'\"{line.strip()}\"', file=fout)
- print(f'/* Sentinel */, \"\"', file=fout)
+ fout.write(f'\n{comma} // Block {block} of {blocks}\nR"(')
+ else:
+ fout.write('\n')
+ fout.write(line.strip())
+ fout.write(')"\n\n/* Sentinel */, ""\n')
def _embed_bytefile(fin, fout, is_text):
diff --git a/sources/shiboken6/libshiboken/embed/signature_bootstrap.py b/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
index c11a0367a..37f95cd35 100644
--- a/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
+++ b/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
@@ -26,6 +26,7 @@ recursion_trap = 0
import base64
import importlib
import io
+import os
import sys
import traceback
import zipfile
@@ -61,21 +62,83 @@ def bootstrap():
import shibokensupport
yield
except Exception as e:
- print("Problem importing shibokensupport:")
- print(f"{e.__class__.__name__}: {e}")
+ f = sys.stderr
+ print("Problem importing shibokensupport:", file=f)
+ print(f"{e.__class__.__name__}: {e}", file=f)
traceback.print_exc()
- print("sys.path:")
+ print("sys.path:", file=f)
for p in sys.path:
- print(" " + p)
- sys.stdout.flush()
+ print(" " + p, file=f)
+ f.flush()
sys.exit(-1)
target.remove(support_path)
- target, support_path = prepare_zipfile()
+ # Here we decide if we re-incarnate the embedded files or use embedding.
+ incarnated = find_incarnated_files()
+ if incarnated:
+ target, support_path = sys.path, os.fspath(incarnated)
+ else:
+ target, support_path = prepare_zipfile()
with ensure_shibokensupport(target, support_path):
from shibokensupport.signature import loader
return loader
+# Newer functionality:
+# This function checks if the support directory exist and returns it.
+# If does not exist, we try to create it and return it.
+# Otherwise, we return None.
+
+def find_incarnated_files():
+ import shiboken6 as root
+ files_dir = Path(root.__file__).resolve().parent / "files.dir"
+ handle_embedding_switch(files_dir)
+ if files_dir.exists():
+ sys.path.insert(0, os.fspath(files_dir))
+ # Note: To avoid recursion problems, we need to preload the loader.
+ # But that has the side-effect that we need to delay the feature
+ # initialization until all function pointers are set.
+ # See `post_init_func` in signature_globals.cpp .
+ import shibokensupport.signature.loader
+ del sys.path[0]
+ return files_dir
+ return None
+
+
+def handle_embedding_switch(files_dir):
+ """
+ This handles the optional environment variable `SBK_EMBED`
+ if not set : do nothing
+ if set to 0, false, no : de-virtualize the Python files
+ if set to 1, true, yes : virtualize again (delete "files.dir")
+ """
+ env_name = "SBK_EMBED"
+ env_var = os.environ.get(env_name)
+ if not env_var:
+ return
+ if env_var.lower() in ("1", "t", "true", "y", "yes"):
+ import shutil
+ shutil.rmtree(files_dir, ignore_errors=True)
+ elif env_var.lower() in ("0", "f", "false", "n", "no"):
+ reincarnate_files(files_dir)
+
+
+def reincarnate_files(files_dir):
+ target, zip = prepare_zipfile()
+ names = (_ for _ in zip.zfile.namelist() if _.endswith(".py"))
+ try:
+ # First check mkdir to get an error when we cannot write.
+ files_dir.mkdir(exist_ok=True)
+ except os.error as e:
+ print(f"SBK_EMBED=False: Warning: Cannot write into {files_dir}")
+ return None
+ try:
+ # Then check for a real error when unpacking the zip file.
+ zip.zfile.extractall(path=files_dir, members=names)
+ return files_dir
+ except Exception as e:
+ print(f"{e.__class__.__name__}: {e}", file=sys.stderr)
+ traceback.print_exc()
+ raise
# New functionality: Loading from a zip archive.
# There exists the zip importer, but as it is written, only real zip files are
diff --git a/sources/shiboken6/libshiboken/helper.cpp b/sources/shiboken6/libshiboken/helper.cpp
index 8f836316e..46af68956 100644
--- a/sources/shiboken6/libshiboken/helper.cpp
+++ b/sources/shiboken6/libshiboken/helper.cpp
@@ -5,28 +5,60 @@
#include "basewrapper_p.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
+#include "sbkstaticstrings.h"
+#include "pep384impl.h"
+
+#include <algorithm>
+#include <optional>
#include <iomanip>
#include <iostream>
-
+#include <climits>
+#include <cstring>
#include <cstdarg>
+#include <cctype>
#ifdef _WIN32
-# ifndef NOMINMAX
-# define NOMINMAX
-# endif
-# include <windows.h>
+# include <sbkwindows.h>
#else
# include <pthread.h>
#endif
-#include <algorithm>
+static std::optional<std::string> getStringAttr(PyObject *obj, const char *what)
+{
+ if (PyObject_HasAttrString(obj, what) != 0) { // Check first to suppress error.
+ Shiboken::AutoDecRef result(PyObject_GetAttrString(obj, what));
+ if (PyUnicode_Check(result.object()) != 0)
+ return _PepUnicode_AsString(result.object());
+ }
+ return std::nullopt;
+}
-static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str)
+static std::optional<int> getIntAttr(PyObject *obj, const char *what)
{
- if (obj) {
- str << '"' << obj->tp_name << "\", 0x" << std::hex
- << obj->tp_flags << std::dec;
+ if (PyObject_HasAttrString(obj, what) != 0) { // Check first to suppress error.
+ Shiboken::AutoDecRef result(PyObject_GetAttrString(obj, what));
+ if (PyLong_Check(result.object()) != 0)
+ return PyLong_AsLong(result.object());
+ }
+ return std::nullopt;
+}
+
+static bool verbose = false;
+
+static void formatTypeTuple(PyObject *t, const char *what, std::ostream &str);
+
+static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str, bool verbose)
+{
+ if (obj == nullptr) {
+ str << '0';
+ return;
+ }
+
+ str << '"' << obj->tp_name << '"';
+ if (verbose) {
+ bool immutableType = false;
+ str << ", 0x" << std::hex << obj->tp_flags << std::dec;
if (obj->tp_flags & Py_TPFLAGS_HEAPTYPE)
str << " [heaptype]";
if (obj->tp_flags & Py_TPFLAGS_BASETYPE)
@@ -49,30 +81,59 @@ static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str)
str << " [type]";
if (obj->tp_flags & Py_TPFLAGS_IS_ABSTRACT)
str << " [abstract]";
-#if PY_VERSION_HEX >= 0x03080000
+ if (obj->tp_flags & Py_TPFLAGS_READY)
+ str << " [ready]";
+ if (obj->tp_flags & Py_TPFLAGS_READYING)
+ str << " [readying]";
if (obj->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)
str << " [method_descriptor]";
-# if PY_VERSION_HEX >= 0x03090000
-# ifndef Py_LIMITED_API
+# ifndef Py_LIMITED_API
if (obj->tp_flags & Py_TPFLAGS_HAVE_VECTORCALL)
str << " [vectorcall]";
-# endif // !Py_LIMITED_API
-# if PY_VERSION_HEX >= 0x030A0000
- if (obj->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)
+# endif // !Py_LIMITED_API
+# if PY_VERSION_HEX >= 0x030A0000
+ immutableType = (obj->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) != 0;
+ if (immutableType)
str << " [immutabletype]";
if (obj->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION)
str << " [disallow_instantiation]";
-# ifndef Py_LIMITED_API
+# ifndef Py_LIMITED_API
if (obj->tp_flags & Py_TPFLAGS_MAPPING)
str << " [mapping]";
if (obj->tp_flags & Py_TPFLAGS_SEQUENCE)
str << " [sequence]";
# endif // !Py_LIMITED_API
-# endif // 3.10
-# endif // 3.9
-#endif // 3.8
- } else {
- str << '0';
+# endif // 3.10
+ if (obj->tp_basicsize != 0)
+ str << ", basicsize=" << obj->tp_basicsize;
+ if (verbose) {
+ formatTypeTuple(obj->tp_bases, "bases", str);
+ formatTypeTuple(obj->tp_mro, "mro", str);
+ if (!immutableType) {
+ auto *underlying = reinterpret_cast<const PyObject *>(obj)->ob_type;
+ if (underlying != nullptr && underlying != obj) {
+ str << ", underlying=\"" << underlying->tp_name << '"';
+ }
+ }
+ }
+ }
+}
+
+static void formatTypeTuple(PyObject *t, const char *what, std::ostream &str)
+{
+ const Py_ssize_t size = t != nullptr && PyTuple_Check(t) != 0 ? PyTuple_Size(t) : 0;
+ if (size > 0) {
+ str << ", " << what << "=[" << size << "]{";
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ if (i != 0)
+ str << ", ";
+ Shiboken::AutoDecRef item(PyTuple_GetItem(t, i));
+ if (item.isNull())
+ str << '0'; // Observed with non-ready types
+ else
+ str << '"' << reinterpret_cast<PyTypeObject *>(item.object())->tp_name << '"';
+ }
+ str << '}';
}
}
@@ -151,13 +212,17 @@ static void formatPyUnicode(PyObject *obj, std::ostream &str)
{
// Note: The below call create the PyCompactUnicodeObject.utf8 representation
str << '"' << _PepUnicode_AsString(obj) << '"';
+ if (!verbose)
+ return;
str << " (" << PyUnicode_GetLength(obj) << ')';
const auto kind = _PepUnicode_KIND(obj);
switch (kind) {
+#if PY_VERSION_HEX < 0x030C0000
case PepUnicode_WCHAR_KIND:
str << " [wchar]";
break;
+#endif
case PepUnicode_1BYTE_KIND:
str << " [1byte]";
break;
@@ -178,8 +243,10 @@ static void formatPyUnicode(PyObject *obj, std::ostream &str)
void *data =_PepUnicode_DATA(obj);
str << ", data=";
switch (kind) {
+#if PY_VERSION_HEX < 0x030C0000
case PepUnicode_WCHAR_KIND:
formatCharSequence(reinterpret_cast<const wchar_t *>(data), str);
+#endif
break;
case PepUnicode_1BYTE_KIND:
formatCharSequence(reinterpret_cast<const Py_UCS1 *>(data), str);
@@ -208,22 +275,92 @@ static void formatPyUnicode(PyObject *obj, std::ostream &str)
#endif // !Py_LIMITED_API
}
+static std::string getQualName(PyObject *obj)
+{
+ Shiboken::AutoDecRef result(PyObject_GetAttr(obj, Shiboken::PyMagicName::qualname()));
+ return result.object() != nullptr
+ ? _PepUnicode_AsString(result.object()) : std::string{};
+}
+
+static void formatPyFunction(PyObject *obj, std::ostream &str)
+{
+ str << '"' << getQualName(obj) << "()\"";
+}
+
+static void formatPyMethod(PyObject *obj, std::ostream &str)
+{
+ if (auto *func = PyMethod_Function(obj))
+ formatPyFunction(func, str);
+ str << ", instance=" << PyMethod_Self(obj);
+}
+
+static void formatPyCodeObject(PyObject *obj, std::ostream &str)
+{
+ if (auto name = getStringAttr(obj, "co_name"))
+ str << '"' << name.value() << '"';
+ if (auto qualName = getStringAttr(obj, "co_qualname"))
+ str << ", co_qualname=\"" << qualName.value() << '"';
+ if (auto flags = getIntAttr(obj, "co_flags"))
+ str << ", flags=0x" << std::hex << flags.value() << std::dec;
+ if (auto c = getIntAttr(obj, "co_argcount"))
+ str << ", co_argcounts=" << c.value();
+ if (auto c = getIntAttr(obj, "co_posonlyargcount"))
+ str << ", co_posonlyargcount=" << c.value();
+ if (auto c = getIntAttr(obj, "co_kwonlyargcount"))
+ str << ", co_kwonlyargcount=" << c.value();
+ if (auto fileName = getStringAttr(obj, "co_filename")) {
+ str << " @" << fileName.value();
+ if (auto l = getIntAttr(obj, "co_firstlineno"))
+ str << ':'<< l.value();
+ }
+}
+
static void formatPyObjectHelper(PyObject *obj, std::ostream &str)
{
- str << ", refs=" << obj->ob_refcnt << ", ";
+ str << ", ";
+ if (obj == Py_None) {
+ str << "None";
+ return;
+ }
+ if (obj == Py_True) {
+ str << "True";
+ return;
+ }
+ if (obj == Py_False) {
+ str << "False";
+ return;
+ }
+ const auto refs = Py_REFCNT(obj);
+ if (refs == UINT_MAX) // _Py_IMMORTAL_REFCNT
+ str << "immortal, ";
+ else
+ str << "refs=" << refs << ", ";
if (PyType_Check(obj)) {
str << "type: ";
- formatPyTypeObject(reinterpret_cast<PyTypeObject *>(obj), str);
+ formatPyTypeObject(reinterpret_cast<PyTypeObject *>(obj), str, true);
return;
}
- formatPyTypeObject(obj->ob_type, str);
+ formatPyTypeObject(obj->ob_type, str, false);
str << ", ";
- if (PyLong_Check(obj))
- str << PyLong_AsLong(obj);
+ if (PyLong_Check(obj)) {
+ const auto llv = PyLong_AsLongLong(obj);
+ if (PyErr_Occurred() != PyExc_OverflowError) {
+ str << llv;
+ } else {
+ PyErr_Clear();
+ str << "0x" << std::hex << PyLong_AsUnsignedLongLong(obj) << std::dec;
+ }
+ }
else if (PyFloat_Check(obj))
str << PyFloat_AsDouble(obj);
else if (PyUnicode_Check(obj))
formatPyUnicode(obj, str);
+ else if (PyFunction_Check(obj) != 0)
+ formatPyFunction(obj, str);
+ else if (PyMethod_Check(obj) != 0)
+ formatPyMethod(obj, str);
+ else if (PepCode_Check(obj) != 0)
+ formatPyCodeObject(obj, str);
else if (PySequence_Check(obj))
formatPySequence(obj, str);
else if (PyDict_Check(obj))
@@ -263,7 +400,7 @@ debugPyBuffer::debugPyBuffer(const Py_buffer &b) : m_buffer(b)
std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o)
{
str << "PyTypeObject(";
- formatPyTypeObject(o.m_object, str);
+ formatPyTypeObject(o.m_object, str, true);
str << ')';
return str;
}
@@ -299,6 +436,18 @@ std::ostream &operator<<(std::ostream &str, const debugPyBuffer &b)
return str;
}
+std::ios_base &debugVerbose(std::ios_base &s)
+{
+ verbose = true;
+ return s;
+}
+
+std::ios_base &debugBrief(std::ios_base &s)
+{
+ verbose = false;
+ return s;
+}
+
#ifdef _WIN32
// Converts a Unicode string to a string encoded in the Windows console's
// code page via wchar_t for use with argv (PYSIDE-1425).
@@ -442,4 +591,47 @@ ThreadId mainThreadId()
return _mainThreadId;
}
+const char *typeNameOf(const char *typeIdName)
+{
+ auto size = std::strlen(typeIdName);
+#if defined(Q_CC_MSVC) // MSVC: "class QPaintDevice * __ptr64"
+ if (auto *lastStar = strchr(typeName, '*')) {
+ // MSVC: "class QPaintDevice * __ptr64"
+ while (*--lastStar == ' ') {
+ }
+ size = lastStar - typeName + 1;
+ }
+#else // g++, Clang: "QPaintDevice *" -> "P12QPaintDevice"
+ if (size > 2 && typeIdName[0] == 'P' && std::isdigit(typeIdName[1])) {
+ ++typeIdName;
+ --size;
+ }
+#endif
+ char *result = new char[size + 1];
+ result[size] = '\0';
+ std::memcpy(result, typeIdName, size);
+ return result;
+}
+
+#if !defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x030A0000 && !defined(PYPY_VERSION)
+static int _getPyVerbose()
+{
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ return config.verbose;
+}
+#endif // !Py_LIMITED_API >= 3.10
+
+int pyVerbose()
+{
+#ifdef Py_LIMITED_API
+ return Pep_GetVerboseFlag();
+#elif PY_VERSION_HEX >= 0x030A0000 && !defined(PYPY_VERSION)
+ static const int result = _getPyVerbose();
+ return result;
+#else
+ return Py_VerboseFlag;
+#endif
+}
+
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/helper.h b/sources/shiboken6/libshiboken/helper.h
index 265bb6581..f226e8c24 100644
--- a/sources/shiboken6/libshiboken/helper.h
+++ b/sources/shiboken6/libshiboken/helper.h
@@ -36,6 +36,10 @@ LIBSHIBOKEN_API bool listToArgcArgv(PyObject *argList, int *argc, char ***argv,
*/
LIBSHIBOKEN_API int *sequenceToIntArray(PyObject *obj, bool zeroTerminated = false);
+/// Fix a type name returned by typeid(t).name(), depending on compiler.
+/// \returns Fixed name (allocated).
+LIBSHIBOKEN_API const char *typeNameOf(const char *typeIdName);
+
/**
* Creates and automatically deallocates C++ arrays.
*/
@@ -61,6 +65,8 @@ using ThreadId = unsigned long long;
LIBSHIBOKEN_API ThreadId currentThreadId();
LIBSHIBOKEN_API ThreadId mainThreadId();
+LIBSHIBOKEN_API int pyVerbose();
+
/**
* An utility function used to call PyErr_WarnEx with a formatted message.
*/
@@ -106,7 +112,8 @@ LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugSbkObject
LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o);
LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyBuffer &b);
LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &b);
-
+LIBSHIBOKEN_API std::ios_base &debugVerbose(std::ios_base &s);
+LIBSHIBOKEN_API std::ios_base &debugBrief(std::ios_base &s);
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/pep384_issue33738.cpp b/sources/shiboken6/libshiboken/pep384_issue33738.cpp
deleted file mode 100644
index 7f3872a58..000000000
--- a/sources/shiboken6/libshiboken/pep384_issue33738.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-// There is a bug in Python 3.6 that turned the Index_Check function
-// into a macro without taking care of the limited API.
-// This leads to the single problem that we don't have
-// access to PyLong_Type's nb_index field which is no heap type.
-// We cannot easily create this function by inheritance since it is
-// not inherited.
-//
-// Simple solution: Create the structure and write such a function.
-// Long term: Submit a patch to python.org .
-
-// This structure comes from Python 3.7, but we have checked that
-// it also works for Python 3.8 and 3.9.
-
-typedef struct {
- /* Number implementations must check *both*
- arguments for proper type and implement the necessary conversions
- in the slot functions themselves. */
-
- binaryfunc nb_add;
- binaryfunc nb_subtract;
- binaryfunc nb_multiply;
- binaryfunc nb_remainder;
- binaryfunc nb_divmod;
- ternaryfunc nb_power;
- unaryfunc nb_negative;
- unaryfunc nb_positive;
- unaryfunc nb_absolute;
- inquiry nb_bool;
- unaryfunc nb_invert;
- binaryfunc nb_lshift;
- binaryfunc nb_rshift;
- binaryfunc nb_and;
- binaryfunc nb_xor;
- binaryfunc nb_or;
- unaryfunc nb_int;
- void *nb_reserved; /* the slot formerly known as nb_long */
- unaryfunc nb_float;
-
- binaryfunc nb_inplace_add;
- binaryfunc nb_inplace_subtract;
- binaryfunc nb_inplace_multiply;
- binaryfunc nb_inplace_remainder;
- ternaryfunc nb_inplace_power;
- binaryfunc nb_inplace_lshift;
- binaryfunc nb_inplace_rshift;
- binaryfunc nb_inplace_and;
- binaryfunc nb_inplace_xor;
- binaryfunc nb_inplace_or;
-
- binaryfunc nb_floor_divide;
- binaryfunc nb_true_divide;
- binaryfunc nb_inplace_floor_divide;
- binaryfunc nb_inplace_true_divide;
-
- unaryfunc nb_index;
-
- binaryfunc nb_matrix_multiply;
- binaryfunc nb_inplace_matrix_multiply;
-} PyNumberMethods;
-
-// temporary structure until we have a generator for the offsets
-typedef struct _oldtypeobject {
- PyVarObject ob_base;
- void *X01; // const char *tp_name;
- void *X02; // Py_ssize_t tp_basicsize;
- void *X03; // Py_ssize_t tp_itemsize;
- void *X04; // destructor tp_dealloc;
- void *X05; // printfunc tp_print;
- void *X06; // getattrfunc tp_getattr;
- void *X07; // setattrfunc tp_setattr;
- void *X08; // PyAsyncMethods *tp_as_async;
- void *X09; // reprfunc tp_repr;
- PyNumberMethods *tp_as_number;
-
-} PyOldTypeObject;
-
-static bool is_compatible_version()
-{
- auto *sysmodule = PyImport_AddModule("sys");
- auto *dic = PyModule_GetDict(sysmodule);
- auto *version = PyDict_GetItemString(dic, "version_info");
- auto *major = PyTuple_GetItem(version, 0);
- auto *minor = PyTuple_GetItem(version, 1);
- auto number = PyLong_AsLong(major) * 1000 + PyLong_AsLong(minor);
- return number < 3010;
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// PYSIE-1797: The Solution
-// ========================
-//
-// Inspecting the data structures of Python 3.6, 3.7, 3.8 and 3.9
-// shows that concerning the here needed offset of nb_index, they
-// are all compatible.
-// That means: We can use the above definition for all these versions.
-//
-// From Python 3.10 on, the `PyType_GetSlot` function also works with
-// non-heap types. That means this solution will always work.
-//
-// Note: When we have moved to Python 3.8 as the minimum version,
-// this whole nonsense can be trashed.
-// There is an automatic warning about this in parser.py .
-//
-
-LIBSHIBOKEN_API int PepIndex_Check(PyObject *obj)
-{
- static bool old_python_version = is_compatible_version();
- if (old_python_version) {
- auto *type = reinterpret_cast<PyOldTypeObject *>(Py_TYPE(obj));
- return type->tp_as_number != nullptr &&
- type->tp_as_number->nb_index != nullptr;
- }
- // From Python 3.10 on, we can use PyType_GetSlot also with normal types!
- unaryfunc nb_index = reinterpret_cast<unaryfunc>(PyType_GetSlot(Py_TYPE(obj), Py_nb_index));
- return nb_index != nullptr;
-}
-
diff --git a/sources/shiboken6/libshiboken/pep384ext.h b/sources/shiboken6/libshiboken/pep384ext.h
new file mode 100644
index 000000000..021c53d16
--- /dev/null
+++ b/sources/shiboken6/libshiboken/pep384ext.h
@@ -0,0 +1,89 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef PEP384EXT_H
+#define PEP384EXT_H
+
+#include "pep384impl.h"
+
+/// Returns the allocator slot of the PyTypeObject.
+inline allocfunc PepExt_Type_GetAllocSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<allocfunc>(PepType_GetSlot(t, Py_tp_alloc));
+}
+
+/// Invokes the allocator slot of the PyTypeObject.
+template <class Type>
+inline Type *PepExt_TypeCallAlloc(PyTypeObject *t, Py_ssize_t nitems)
+{
+ PyObject *result = PepExt_Type_GetAllocSlot(t)(t, nitems);
+ return reinterpret_cast<Type *>(result);
+}
+
+/// Returns the getattro slot of the PyTypeObject.
+inline getattrofunc PepExt_Type_GetGetAttroSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<getattrofunc>(PepType_GetSlot(t, Py_tp_getattro));
+}
+
+/// Returns the setattro slot of the PyTypeObject.
+inline setattrofunc PepExt_Type_GetSetAttroSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<setattrofunc>(PepType_GetSlot(t, Py_tp_setattro));
+}
+
+/// Returns the descr_get slot of the PyTypeObject.
+inline descrgetfunc PepExt_Type_GetDescrGetSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<descrgetfunc>(PepType_GetSlot(t, Py_tp_descr_get));
+}
+
+/// Invokes the descr_get slot of the PyTypeObject.
+inline PyObject *PepExt_Type_CallDescrGet(PyObject *self, PyObject *obj, PyObject *type)
+{
+ return PepExt_Type_GetDescrGetSlot(Py_TYPE(self))(self, obj, type);
+}
+
+/// Returns the descr_set slot of the PyTypeObject.
+inline descrsetfunc PepExt_Type_GetDescrSetSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<descrsetfunc>(PepType_GetSlot(t, Py_tp_descr_set));
+}
+
+/// Returns the call slot of the PyTypeObject.
+inline ternaryfunc PepExt_Type_GetCallSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<ternaryfunc>(PepType_GetSlot(t, Py_tp_call));
+}
+
+/// Returns the new slot of the PyTypeObject.
+inline newfunc PepExt_Type_GetNewSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<newfunc>(PepType_GetSlot(t, Py_tp_new));
+}
+
+/// Returns the init slot of the PyTypeObject.
+inline initproc PepExt_Type_GetInitSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<initproc>(PepType_GetSlot(t, Py_tp_init));
+}
+
+/// Returns the free slot of the PyTypeObject.
+inline freefunc PepExt_Type_GetFreeSlot(PyTypeObject *t)
+{
+ return reinterpret_cast<freefunc>(PepType_GetSlot(t, Py_tp_free));
+}
+
+/// Invokes the free slot of the PyTypeObject.
+inline void PepExt_TypeCallFree(PyTypeObject *t, void *object)
+{
+ PepExt_Type_GetFreeSlot(t)(object);
+}
+
+/// Invokes the free slot of the PyTypeObject.
+inline void PepExt_TypeCallFree(PyObject *object)
+{
+ PepExt_Type_GetFreeSlot(Py_TYPE(object))(object);
+}
+
+#endif // PEP384EXT_H
diff --git a/sources/shiboken6/libshiboken/pep384impl.cpp b/sources/shiboken6/libshiboken/pep384impl.cpp
index cdf3d96dc..f926107e2 100644
--- a/sources/shiboken6/libshiboken/pep384impl.cpp
+++ b/sources/shiboken6/libshiboken/pep384impl.cpp
@@ -1,6 +1,8 @@
-// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#define PEP384_INTERN
+
#include "sbkpython.h"
#include "autodecref.h"
#include "sbkstaticstrings.h"
@@ -8,8 +10,6 @@
#include "basewrapper.h"
#include "basewrapper_p.h"
#include "sbkenum.h"
-#include "sbkenum_p.h"
-#include "sbkconverter.h"
#include "voidptr.h"
#include <cstdlib>
@@ -19,7 +19,7 @@ extern "C"
{
/*
- * The documentation is located in pep384impl_doc.rst
+ * The documentation is located in `sources/pyside6/doc/developer/limited_api.rst`.
* Here is the verification code for PyTypeObject.
* We create a type object and check if its fields
@@ -37,16 +37,16 @@ dummy_func(PyObject * /* self */, PyObject * /* args */)
}
static struct PyMethodDef probe_methoddef[] = {
- {"dummy", dummy_func, METH_NOARGS},
- {nullptr}
+ {"dummy", dummy_func, METH_NOARGS, nullptr},
+ {nullptr, nullptr, 0, nullptr}
};
static PyGetSetDef probe_getseters[] = {
- {nullptr} /* Sentinel */
+ {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
static PyMemberDef probe_members[] = {
- {nullptr} /* Sentinel */
+ {nullptr, 0, 0, 0, nullptr} /* Sentinel */
};
#define probe_tp_dealloc make_dummy(1)
@@ -117,6 +117,8 @@ check_PyTypeObject_valid()
PyObject *d = PyObject_GetAttr(obtype, Shiboken::PyMagicName::dictoffset());
long probe_tp_dictoffset = PyLong_AsLong(d);
PyObject *probe_tp_mro = PyObject_GetAttr(obtype, Shiboken::PyMagicName::mro());
+ Shiboken::AutoDecRef tpDict(PepType_GetDict(check));
+ auto *checkDict = tpDict.object();
if (false
|| strcmp(probe_tp_name, check->tp_name) != 0
|| probe_tp_basicsize != check->tp_basicsize
@@ -133,8 +135,8 @@ check_PyTypeObject_valid()
|| probe_tp_methods != check->tp_methods
|| probe_tp_getset != check->tp_getset
|| probe_tp_base != typetype->tp_base
- || !PyDict_Check(check->tp_dict)
- || !PyDict_GetItemString(check->tp_dict, "dummy")
+ || !PyDict_Check(checkDict)
+ || !PyDict_GetItemString(checkDict, "dummy")
|| probe_tp_descr_get != check->tp_descr_get
|| probe_tp_descr_set != check->tp_descr_set
|| probe_tp_dictoffset != typetype->tp_dictoffset
@@ -155,9 +157,6 @@ check_PyTypeObject_valid()
Py_DECREF(probe_tp_mro);
}
-// PYSIDE-1797: This must be a runtime decision.
-#include "pep384_issue33738.cpp"
-
#endif // Py_LIMITED_API
/*****************************************************************************
@@ -179,7 +178,7 @@ static PyObject *
find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
{
Py_ssize_t i, n;
- PyObject *mro, *res, *base, *dict;
+ PyObject *mro, *res, *base;
/* Look in tp_dict of types in MRO */
mro = type->tp_mro;
@@ -193,9 +192,10 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
for (i = 0; i < n; i++) {
base = PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(base));
- dict = ((PyTypeObject *)base)->tp_dict;
- assert(dict && PyDict_Check(dict));
- res = PyDict_GetItem(dict, name);
+ auto *type = reinterpret_cast<PyTypeObject *>(base);
+ Shiboken::AutoDecRef dict(PepType_GetDict(type));
+ assert(!dict.isNull() && PyDict_Check(dict.object()));
+ res = PyDict_GetItem(dict.object(), name);
if (res != nullptr)
break;
if (PyErr_Occurred()) {
@@ -251,7 +251,7 @@ _PepType_Lookup(PyTypeObject *type, PyObject *name)
// structs and macros modelled after their equivalents in
// cpython/Include/cpython/unicodeobject.h
-struct PepASCIIObject
+struct PepASCIIObject // since 3.12
{
PyObject_HEAD
Py_ssize_t length; /* Number of code points in the string */
@@ -264,18 +264,29 @@ struct PepASCIIObject
unsigned int ready:1;
unsigned int :24;
} state;
+};
+
+struct PepASCIIObject_311 : public PepASCIIObject
+{
wchar_t *wstr; /* wchar_t representation (null-terminated) */
};
-struct PepCompactUnicodeObject
+struct PepCompactUnicodeObject // since 3.12
{
PepASCIIObject _base;
Py_ssize_t utf8_length;
char *utf8; /* UTF-8 representation (null-terminated) */
+};
+
+struct PepCompactUnicodeObject_311 // since 3.12
+{
+ PepASCIIObject_311 _base;
+ Py_ssize_t utf8_length;
+ char *utf8; /* UTF-8 representation (null-terminated) */
Py_ssize_t wstr_length; /* Number of code points in wstr */
};
-struct PepUnicodeObject
+struct PepUnicodeObject // since 3.12
{
PepCompactUnicodeObject _base;
union {
@@ -286,6 +297,17 @@ struct PepUnicodeObject
} data; /* Canonical, smallest-form Unicode buffer */
};
+struct PepUnicodeObject_311
+{
+ PepCompactUnicodeObject_311 _base;
+ union {
+ void *any;
+ Py_UCS1 *latin1;
+ Py_UCS2 *ucs2;
+ Py_UCS4 *ucs4;
+ } data; /* Canonical, smallest-form Unicode buffer */
+};
+
int _PepUnicode_KIND(PyObject *str)
{
return reinterpret_cast<PepASCIIObject *>(str)->state.kind;
@@ -303,18 +325,33 @@ int _PepUnicode_IS_COMPACT(PyObject *str)
return asciiObj->state.compact;
}
-static void *_PepUnicode_COMPACT_DATA(PyObject *str)
+static void *_PepUnicode_ASCII_DATA(PyObject *str)
{
+ if (_PepRuntimeVersion() < 0x030C00) {
+ auto *asciiObj_311 = reinterpret_cast<PepASCIIObject_311 *>(str);
+ return asciiObj_311 + 1;
+ }
auto *asciiObj = reinterpret_cast<PepASCIIObject *>(str);
- if (asciiObj->state.ascii)
- return asciiObj + 1;
+ return asciiObj + 1;
+}
+
+static void *_PepUnicode_COMPACT_DATA(PyObject *str)
+{
+ if (_PepUnicode_IS_ASCII(str) != 0)
+ return _PepUnicode_ASCII_DATA(str);
+ if (_PepRuntimeVersion() < 0x030C00) {
+ auto *compactObj_311 = reinterpret_cast<PepCompactUnicodeObject_311 *>(str);
+ return compactObj_311 + 1;
+ }
auto *compactObj = reinterpret_cast<PepCompactUnicodeObject *>(str);
return compactObj + 1;
}
static void *_PepUnicode_NONCOMPACT_DATA(PyObject *str)
{
- return reinterpret_cast<PepUnicodeObject *>(str)->data.any;
+ return _PepRuntimeVersion() < 0x030C00
+ ? reinterpret_cast<PepUnicodeObject_311 *>(str)->data.any
+ : reinterpret_cast<PepUnicodeObject *>(str)->data.any;
}
void *_PepUnicode_DATA(PyObject *str)
@@ -325,6 +362,23 @@ void *_PepUnicode_DATA(PyObject *str)
// Fast path accessing UTF8 data without doing a conversion similar
// to _PyUnicode_AsUTF8String
+static const char *utf8FastPath_311(PyObject *str)
+{
+ if (PyUnicode_GetLength(str) == 0)
+ return "";
+ auto *asciiObj = reinterpret_cast<PepASCIIObject_311 *>(str);
+ if (asciiObj->state.kind != PepUnicode_1BYTE_KIND || asciiObj->state.compact == 0)
+ return nullptr; // Empirical: PyCompactUnicodeObject.utf8 is only valid for 1 byte
+ if (asciiObj->state.ascii) {
+ auto *data = asciiObj + 1;
+ return reinterpret_cast<const char *>(data);
+ }
+ auto *compactObj = reinterpret_cast<PepCompactUnicodeObject_311 *>(str);
+ if (compactObj->utf8_length)
+ return compactObj->utf8;
+ return nullptr;
+}
+
static const char *utf8FastPath(PyObject *str)
{
if (PyUnicode_GetLength(str) == 0)
@@ -345,18 +399,21 @@ static const char *utf8FastPath(PyObject *str)
const char *_PepUnicode_AsString(PyObject *str)
{
/*
- * We need to keep the string alive but cannot borrow the Python object.
- * Ugly easy way out: We re-code as an interned bytes string. This
- * produces a pseudo-leak as long as there are new strings.
- * Typically, this function is used for name strings, and the dict size
- * will not grow so much.
+ * This function is the surrogate for PyUnicode_AsUTF8, which keeps the data
+ * in the unicode object as long as that object exists.
+ *
+ * The function does too much if not optimized by utf8, because it keeps the
+ * string alive, unconditionally.
+ * We should not rely on this behavior and think of PyUnicode_AsUTF8, only.
*/
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
- if (const auto *utf8 = utf8FastPath(str))
+ if (const auto *utf8 = _PepRuntimeVersion() < 0x030C00
+ ? utf8FastPath_311(str) : utf8FastPath(str)) {
return utf8;
+ }
static PyObject *cstring_dict = nullptr;
if (cstring_dict == nullptr) {
@@ -447,8 +504,24 @@ PepCode_Get(PepCodeObject *co, const char *name)
}
return ret;
}
+
+int PepCode_Check(PyObject *o)
+{
+ return o != nullptr && std::strcmp(Py_TYPE(o)->tp_name, "code") == 0 ? 1 : 0;
+}
+
#endif // Py_LIMITED_API
+#if defined(Py_LIMITED_API) || defined(PYPY_VERSION)
+PyObject *PepFunction_GetDefaults(PyObject *function)
+{
+ auto *ob_ret = PyObject_GetAttrString(function, "__defaults__");
+ Py_XDECREF(ob_ret); // returns borrowed ref
+ return ob_ret != Py_None ? ob_ret : nullptr;
+}
+
+#endif // defined(Py_LIMITED_API) || defined(PYPY_VERSION)
+
/*****************************************************************************
*
* Support for datetime.h
@@ -718,12 +791,37 @@ PepType_GetNameStr(PyTypeObject *type)
return ret;
}
+// PYSIDE-2264: Find the _functools or functools module and retrieve the
+// partial function. This can be tampered with, check carefully.
+PyObject *
+Pep_GetPartialFunction(void)
+{
+ static bool initialized = false;
+ static PyObject *result{};
+ if (initialized) {
+ Py_INCREF(result);
+ return result;
+ }
+ auto *functools = PyImport_ImportModule("_functools");
+ if (!functools) {
+ PyErr_Clear();
+ functools = PyImport_ImportModule("functools");
+ }
+ if (!functools)
+ Py_FatalError("functools cannot be found");
+ result = PyObject_GetAttrString(functools, "partial");
+ if (!result || !PyCallable_Check(result))
+ Py_FatalError("partial not found or not a function");
+ initialized = true;
+ return result;
+}
+
/*****************************************************************************
*
* Newly introduced convenience functions
*
*/
-#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+#ifdef Py_LIMITED_API
PyObject *
PyImport_GetModule(PyObject *name)
@@ -749,7 +847,7 @@ PyImport_GetModule(PyObject *name)
return m;
}
-#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+#endif // Py_LIMITED_API
// 2020-06-16: For simplicity of creating arbitrary things, this function
// is now made public.
@@ -840,13 +938,13 @@ _Pep_PrivateMangle(PyObject *self, PyObject *name)
wchar_t bigbuf[big_stack];
wchar_t *resbuf = amount <= big_stack ? bigbuf : (wchar_t *)malloc(sizeof(wchar_t) * amount);
if (!resbuf)
- return 0;
+ return nullptr;
/* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */
resbuf[0] = '_';
if (PyUnicode_AsWideChar(privateobj, resbuf + 1, ipriv + plen) < 0)
- return 0;
+ return nullptr;
if (PyUnicode_AsWideChar(name, resbuf + ipriv + plen + 1, nlen) < 0)
- return 0;
+ return nullptr;
PyObject *result = PyUnicode_FromWideChar(resbuf + ipriv, 1 + plen + nlen);
if (amount > big_stack)
free(resbuf);
@@ -872,6 +970,21 @@ init_PepRuntime()
PepRuntime_38_flag = 1;
}
+static long _GetPepRuntimeVersion()
+{
+ auto *version = PySys_GetObject("version_info");
+ const auto major = PyLong_AsLong(PyTuple_GetItem(version, 0));
+ const auto minor = PyLong_AsLong(PyTuple_GetItem(version, 1));
+ const auto micro = PyLong_AsLong(PyTuple_GetItem(version, 2));
+ return major << 16 | minor << 8 | micro;
+}
+
+long _PepRuntimeVersion()
+{
+ static const auto number = _GetPepRuntimeVersion();
+ return number;
+}
+
/*****************************************************************************
*
* PYSIDE-535: Support for PyPy
@@ -881,33 +994,108 @@ init_PepRuntime()
*
*/
+///////////////////////////////////////////////////////////////////////
+//
+// PEP 697: Support for embedded type structures.
+//
+// According to `https://docs.python.org/3/c-api/object.html?highlight=pyobject_gettypedata#c.PyObject_GetTypeData`
+// the function `PyObject_GetTypeData` should belong to the Stable API
+// since version 3.12.0, but it does not. We use instead some copies
+// from Python source code.
+
+#if !defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x030C0000
+
+# define PepObject_GetTypeData PyObject_GetTypeData
+
+SbkObjectTypePrivate *PepType_SOTP(PyTypeObject *type)
+{
+ // PYSIDE-2676: Use the meta type explicitly.
+ // A derived type would fail the offset calculation.
+ static auto *meta = SbkObjectType_TypeF();
+ assert(SbkObjectType_Check(type));
+ auto *obType = reinterpret_cast<PyObject *>(type);
+ void *data = PyObject_GetTypeData(obType, meta);
+ return reinterpret_cast<SbkObjectTypePrivate *>(data);
+}
+
+void PepType_SOTP_delete(PyTypeObject * /*type*/)
+{
+}
+
+#else
+
+// The following comments are directly copied from Python 3.12
+//
+
+// Make sure we have maximum alignment, even if the current compiler
+// does not support max_align_t. Note that:
+// - Autoconf reports alignment of unknown types to 0.
+// - 'long double' has maximum alignment on *most* platforms,
+// looks like the best we can do for pre-C11 compilers.
+// - The value is tested, see test_alignof_max_align_t
+# if !defined(ALIGNOF_MAX_ALIGN_T) || ALIGNOF_MAX_ALIGN_T == 0
+# undef ALIGNOF_MAX_ALIGN_T
+# define ALIGNOF_MAX_ALIGN_T alignof(long double)
+# endif
+
+/* Align up to the nearest multiple of alignof(max_align_t)
+ * (like _Py_ALIGN_UP, but for a size rather than pointer)
+ */
+static Py_ssize_t _align_up(Py_ssize_t size)
+{
+ return (size + ALIGNOF_MAX_ALIGN_T - 1) & ~(ALIGNOF_MAX_ALIGN_T - 1);
+}
+
+static void *PepObject_GetTypeData(PyObject *obj, PyTypeObject *cls)
+{
+ assert(PyObject_TypeCheck(obj, cls));
+ return reinterpret_cast<char *>(obj) + _align_up(cls->tp_base->tp_basicsize);
+}
+//
+///////////////////////////////////////////////////////////////////////
+
/*
* PyTypeObject extender
*/
+
static std::unordered_map<PyTypeObject *, SbkObjectTypePrivate > SOTP_extender{};
static thread_local PyTypeObject *SOTP_key{};
static thread_local SbkObjectTypePrivate *SOTP_value{};
-SbkObjectTypePrivate *PepType_SOTP(PyTypeObject *sbkType)
+SbkObjectTypePrivate *PepType_SOTP(PyTypeObject *type)
{
- if (sbkType == SOTP_key)
+ static auto *meta = SbkObjectType_TypeF();
+ static bool use_312 = _PepRuntimeVersion() >= 0x030C00;
+ assert(SbkObjectType_Check(type));
+ if (use_312) {
+ auto *obType = reinterpret_cast<PyObject *>(type);
+ void *data = PepObject_GetTypeData(obType, meta);
+ return reinterpret_cast<SbkObjectTypePrivate *>(data);
+ }
+ if (type == SOTP_key)
return SOTP_value;
- auto it = SOTP_extender.find(sbkType);
+ auto it = SOTP_extender.find(type);
if (it == SOTP_extender.end()) {
- it = SOTP_extender.insert({sbkType, {}}).first;
+ it = SOTP_extender.insert({type, {}}).first;
memset(&it->second, 0, sizeof(SbkObjectTypePrivate));
}
- SOTP_key = sbkType;
+ SOTP_key = type;
SOTP_value = &it->second;
return SOTP_value;
}
-void PepType_SOTP_delete(PyTypeObject *sbkType)
+void PepType_SOTP_delete(PyTypeObject *type)
{
- SOTP_extender.erase(sbkType);
+ static bool use_312 = _PepRuntimeVersion() >= 0x030C00;
+ assert(SbkObjectType_Check(type));
+ if (use_312)
+ return;
+ SOTP_extender.erase(type);
SOTP_key = nullptr;
}
+#endif // !defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x030C0000
+
/*
* SbkEnumType extender
*/
@@ -917,6 +1105,7 @@ static thread_local SbkEnumTypePrivate *SETP_value{};
SbkEnumTypePrivate *PepType_SETP(SbkEnumType *enumType)
{
+ // PYSIDE-2230: This makes no sense at all for Enum types.
if (enumType == SETP_key)
return SETP_value;
auto it = SETP_extender.find(enumType);
@@ -935,38 +1124,76 @@ void PepType_SETP_delete(SbkEnumType *enumType)
SETP_key = nullptr;
}
-/*
- * PySideQFlagsType extender
- */
-static std::unordered_map<PySideQFlagsType *, PySideQFlagsTypePrivate> PFTP_extender{};
-static thread_local PySideQFlagsType *PFTP_key{};
-static thread_local PySideQFlagsTypePrivate *PFTP_value{};
-
-PySideQFlagsTypePrivate *PepType_PFTP(PySideQFlagsType *flagsType)
-{
- static PyTypeObject *enumMeta = getPyEnumMeta();
- auto *mappedType = reinterpret_cast<PyTypeObject *>(flagsType);
- auto *metaType = Py_TYPE(mappedType);
- if (metaType == enumMeta) {
- return reinterpret_cast<PySideQFlagsTypePrivate *>(
- PepType_SETP(reinterpret_cast<SbkEnumType *>(flagsType)));
- }
- if (flagsType == PFTP_key)
- return PFTP_value;
- auto it = PFTP_extender.find(flagsType);
- if (it == PFTP_extender.end()) {
- it = PFTP_extender.insert({flagsType, {}}).first;
- memset(&it->second, 0, sizeof(PySideQFlagsTypePrivate));
+#ifdef Py_LIMITED_API
+static PyObject *emulatePyType_GetDict(PyTypeObject *type)
+{
+ if (_PepRuntimeVersion() < 0x030C00 || type->tp_dict) {
+ auto *res = type->tp_dict;
+ Py_XINCREF(res);
+ return res;
}
- PFTP_key = flagsType;
- PFTP_value = &it->second;
- return PFTP_value;
+ // PYSIDE-2230: Here we are really cheating. We don't know how to
+ // access an internal dict, and so we simply pretend
+ // it were an empty dict. This works great for our types.
+ // This was an unexpectedly simple solution :D
+ return PyDict_New();
}
+#endif
-void PepType_PFTP_delete(PySideQFlagsType *flagsType)
+// PyType_GetDict: replacement for <static type>.tp_dict, which is
+// zero for builtin types since 3.12.
+PyObject *PepType_GetDict(PyTypeObject *type)
{
- PFTP_extender.erase(flagsType);
- PFTP_key = nullptr;
+#if !defined(Py_LIMITED_API)
+# if PY_VERSION_HEX >= 0x030C0000
+ return PyType_GetDict(type);
+# else
+ // pre 3.12 fallback code, mimicking the addref-behavior.
+ Py_XINCREF(type->tp_dict);
+ return type->tp_dict;
+# endif
+#else
+ return emulatePyType_GetDict(type);
+#endif // Py_LIMITED_API
+}
+
+int PepType_SetDict(PyTypeObject *type, PyObject *dict)
+{
+ type->tp_dict = dict;
+ return 0;
+}
+
+// Pre 3.10, PyType_GetSlot() would only work for heap types.
+// FIXME: PyType_GetSlot() can be used unconditionally when the
+// minimum limited API version is >= 3.10.
+void *PepType_GetSlot(PyTypeObject *type, int aSlot)
+{
+ static const bool is310 = _PepRuntimeVersion() >= 0x030A00;
+ if (is310 || (type->tp_flags & Py_TPFLAGS_HEAPTYPE) != 0)
+ return PyType_GetSlot(type, aSlot);
+
+ switch (aSlot) {
+ case Py_tp_alloc:
+ return reinterpret_cast<void *>(type->tp_alloc);
+ case Py_tp_getattro:
+ return reinterpret_cast<void *>(type->tp_getattro);
+ case Py_tp_setattro:
+ return reinterpret_cast<void *>(type->tp_setattro);
+ case Py_tp_descr_get:
+ return reinterpret_cast<void *>(type->tp_descr_get);
+ case Py_tp_descr_set:
+ return reinterpret_cast<void *>(type->tp_descr_set);
+ case Py_tp_call:
+ return reinterpret_cast<void *>(type->tp_call);
+ case Py_tp_new:
+ return reinterpret_cast<void *>(type->tp_new);
+ case Py_tp_init:
+ return reinterpret_cast<void *>(type->tp_init);
+ case Py_tp_free:
+ return reinterpret_cast<void *>(type->tp_free);
+ }
+ assert(false);
+ return nullptr;
}
/***************************************************************************
@@ -1000,16 +1227,16 @@ static inline void *PepType_ExTP(PyTypeObject *type, size_t size)
static PyTypeObject *alias{};
const char *kind = size == sizeof(SbkObjectTypePrivate) ? "SOTP" :
size == sizeof(SbkEnumTypePrivate) ? "SETP" :
- size == sizeof(PySideQFlagsTypePrivate) ? "PFTP" :
+ size == sizeof(SbkQFlagsTypePrivate) ? "PFTP" :
"unk.";
fprintf(stderr, "%s:%d %p x %s s=%ld\n", __func__, __LINE__, type, kind, size);
PyObject *kill{};
if (strlen(env_p) > 0) {
- if (size == sizeof(PySideQFlagsTypePrivate)) {
+ if (size == sizeof(SbkQFlagsTypePrivate)) {
if (alias == nullptr)
alias = type;
}
- if (size != sizeof(PySideQFlagsTypePrivate)) {
+ if (size != sizeof(SbkQFlagsTypePrivate)) {
if (type == alias)
Py_INCREF(kill);
}
diff --git a/sources/shiboken6/libshiboken/pep384impl.h b/sources/shiboken6/libshiboken/pep384impl.h
index a1ccad81f..ec58aac81 100644
--- a/sources/shiboken6/libshiboken/pep384impl.h
+++ b/sources/shiboken6/libshiboken/pep384impl.h
@@ -4,11 +4,6 @@
#ifndef PEP384IMPL_H
#define PEP384IMPL_H
-// PYSIDE-1436: Adapt to Python 3.10
-#if PY_VERSION_HEX < 0x030900A4
-# define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0)
-#endif
-
extern "C"
{
@@ -55,42 +50,79 @@ typedef struct _typeobject {
const char *tp_name;
Py_ssize_t tp_basicsize;
void *X03; // Py_ssize_t tp_itemsize;
+#ifdef PEP384_INTERN
destructor tp_dealloc;
+#else
+ destructor X04;
+#endif
void *X05; // Py_ssize_t tp_vectorcall_offset;
void *X06; // getattrfunc tp_getattr;
void *X07; // setattrfunc tp_setattr;
void *X08; // PyAsyncMethods *tp_as_async;
+#ifdef PEP384_INTERN
reprfunc tp_repr;
+#else
+ reprfunc X09;
+#endif
void *X10; // PyNumberMethods *tp_as_number;
void *X11; // PySequenceMethods *tp_as_sequence;
void *X12; // PyMappingMethods *tp_as_mapping;
void *X13; // hashfunc tp_hash;
+#ifdef PEP384_INTERN
ternaryfunc tp_call;
- reprfunc tp_str;
+#else
+ ternaryfunc X14;
+#endif
+ reprfunc tp_str; // Only used for PEP384_INTERN and a shiboken test
getattrofunc tp_getattro;
setattrofunc tp_setattro;
void *X18; // PyBufferProcs *tp_as_buffer;
unsigned long tp_flags;
void *X20; // const char *tp_doc;
+#ifdef PEP384_INTERN
traverseproc tp_traverse;
inquiry tp_clear;
+#else
+ traverseproc X21;
+ inquiry X22;
+#endif
void *X23; // richcmpfunc tp_richcompare;
Py_ssize_t tp_weaklistoffset;
void *X25; // getiterfunc tp_iter;
+#ifdef PEP384_INTERN
iternextfunc tp_iternext;
+#else
+ iternextfunc X26;
+#endif
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
+#ifdef PEP384_INTERN
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
+#else
+ void *X31;
+ descrgetfunc X32;
+ descrsetfunc X33;
+#endif
Py_ssize_t tp_dictoffset;
+#ifdef PEP384_INTERN
initproc tp_init;
allocfunc tp_alloc;
+#else
+ initproc X39;
+ allocfunc X40;
+#endif
newfunc tp_new;
+#ifdef PEP384_INTERN
freefunc tp_free;
inquiry tp_is_gc; /* For PyObject_IS_GC */
+#else
+ freefunc X41;
+ inquiry X42; /* For PyObject_IS_GC */
+#endif
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
@@ -103,24 +135,16 @@ typedef struct _typeobject {
&& (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
#endif
-// This was a macro error in the limited API from the beginning.
-// It was fixed in Python master, but did make it only into Python 3.8 .
-
-// PYSIDE-1797: This must be a runtime decision.
-// Remove that when the minimum Python version is 3.8,
-// because the macro PepIndex_Check bug was fixed then.
-/// FIXME: Remove PepIndex_Check and pep384_issue33738.cpp when Python 3.7 is gone.
-LIBSHIBOKEN_API int PepIndex_Check(PyObject *obj);
-
LIBSHIBOKEN_API PyObject *_PepType_Lookup(PyTypeObject *type, PyObject *name);
#else // Py_LIMITED_API
-#define PepIndex_Check(obj) PyIndex_Check(obj)
#define _PepType_Lookup(type, name) _PyType_Lookup(type, name)
#endif // Py_LIMITED_API
+/// PYSIDE-939: We need the runtime version, given major << 16 + minor << 8 + micro
+LIBSHIBOKEN_API long _PepRuntimeVersion();
/*****************************************************************************
*
* PYSIDE-535: Implement a clean type extension for PyPy
@@ -139,16 +163,15 @@ LIBSHIBOKEN_API SbkEnumTypePrivate *PepType_SETP(SbkEnumType *type);
LIBSHIBOKEN_API void PepType_SETP_delete(SbkEnumType *enumType);
struct PySideQFlagsType;
-struct PySideQFlagsTypePrivate;
-
-LIBSHIBOKEN_API PySideQFlagsTypePrivate *PepType_PFTP(PySideQFlagsType *type);
-LIBSHIBOKEN_API void PepType_PFTP_delete(PySideQFlagsType *flagsType);
+struct SbkQFlagsTypePrivate;
/*****************************************************************************/
// functions used everywhere
LIBSHIBOKEN_API const char *PepType_GetNameStr(PyTypeObject *type);
+LIBSHIBOKEN_API PyObject *Pep_GetPartialFunction(void);
+
/*****************************************************************************
*
* RESOLVED: pydebug.h
@@ -163,7 +186,6 @@ LIBSHIBOKEN_API const char *PepType_GetNameStr(PyTypeObject *type);
*/
LIBSHIBOKEN_API int Pep_GetFlag(const char *name);
LIBSHIBOKEN_API int Pep_GetVerboseFlag(void);
-#define Py_VerboseFlag Pep_GetVerboseFlag()
#endif
/*****************************************************************************
@@ -193,12 +215,17 @@ LIBSHIBOKEN_API int Pep_GetVerboseFlag(void);
// PyUnicode_GetSize is deprecated in favor of PyUnicode_GetLength.
#define PepUnicode_GetLength(op) PyUnicode_GetLength((PyObject *)(op))
+// Unfortunately, we cannot ask this at runtime
+// #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
+// FIXME: Python 3.10: Replace _PepUnicode_AsString by PyUnicode_AsUTF8
#ifdef Py_LIMITED_API
LIBSHIBOKEN_API const char *_PepUnicode_AsString(PyObject *);
enum PepUnicode_Kind {
+#if PY_VERSION_HEX < 0x030C0000
PepUnicode_WCHAR_KIND = 0,
+#endif
PepUnicode_1BYTE_KIND = 1,
PepUnicode_2BYTE_KIND = 2,
PepUnicode_4BYTE_KIND = 4
@@ -213,7 +240,9 @@ LIBSHIBOKEN_API void *_PepUnicode_DATA(PyObject *str);
#else
enum PepUnicode_Kind {
+#if PY_VERSION_HEX < 0x030C0000
PepUnicode_WCHAR_KIND = PyUnicode_WCHAR_KIND,
+#endif
PepUnicode_1BYTE_KIND = PyUnicode_1BYTE_KIND,
PepUnicode_2BYTE_KIND = PyUnicode_2BYTE_KIND,
PepUnicode_4BYTE_KIND = PyUnicode_4BYTE_KIND
@@ -275,7 +304,7 @@ enum PepUnicode_Kind {
#ifdef Py_LIMITED_API
-typedef struct _pycfunc PyCFunctionObject;
+using PyCFunctionObject = struct _pycfunc;
#define PyCFunction_GET_FUNCTION(func) PyCFunction_GetFunction((PyObject *)func)
#define PyCFunction_GET_SELF(func) PyCFunction_GetSelf((PyObject *)func)
#define PyCFunction_GET_FLAGS(func) PyCFunction_GetFlags((PyObject *)func)
@@ -305,11 +334,8 @@ LIBSHIBOKEN_API PyObject *PyRun_String(const char *, int, PyObject *, PyObject *
// buffer functions.
// But this is no problem as we check it's validity for every version.
-#define PYTHON_BUFFER_VERSION_COMPATIBLE (PY_VERSION_HEX >= 0x03030000 && \
- PY_VERSION_HEX < 0x030AFFFF)
-#if !PYTHON_BUFFER_VERSION_COMPATIBLE
-# error Please check the buffer compatibility for this python version!
-#endif
+// PYSIDE-1960 The buffer interface is since Python 3.11 part of the stable
+// API and we do not need to check the compatibility by hand anymore.
typedef struct {
getbufferproc bf_getbuffer;
@@ -393,10 +419,13 @@ LIBSHIBOKEN_API PyObject *PyMethod_Self(PyObject *);
typedef struct _code PepCodeObject;
LIBSHIBOKEN_API int PepCode_Get(PepCodeObject *co, const char *name);
+LIBSHIBOKEN_API int PepCode_Check(PyObject *o);
# define PepCode_GET_FLAGS(o) PepCode_Get(o, "co_flags")
# define PepCode_GET_ARGCOUNT(o) PepCode_Get(o, "co_argcount")
+LIBSHIBOKEN_API PyObject *PepFunction_GetDefaults(PyObject *function);
+
/* Masks for co_flags above */
# define CO_OPTIMIZED 0x0001
# define CO_NEWLOCALS 0x0002
@@ -410,7 +439,15 @@ LIBSHIBOKEN_API int PepCode_Get(PepCodeObject *co, const char *name);
# define PepCodeObject PyCodeObject
# define PepCode_GET_FLAGS(o) ((o)->co_flags)
# define PepCode_GET_ARGCOUNT(o) ((o)->co_argcount)
+# define PepCode_Check PyCode_Check
+
+# ifdef PYPY_VERSION
+LIBSHIBOKEN_API PyObject *PepFunction_GetDefaults(PyObject *function);
+
+# else
+# define PepFunction_GetDefaults PyFunction_GetDefaults
+# endif
#endif
/*****************************************************************************
@@ -511,9 +548,9 @@ extern LIBSHIBOKEN_API PyTypeObject *PepBuiltinMethod_TypePtr;
*
* This is not defined if Py_LIMITED_API is defined.
*/
-#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+#ifdef Py_LIMITED_API
LIBSHIBOKEN_API PyObject *PyImport_GetModule(PyObject *name);
-#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API)
+#endif // Py_LIMITED_API
// Evaluate a script and return the variable `result`
LIBSHIBOKEN_API PyObject *PepRun_GetResult(const char *command);
@@ -538,6 +575,20 @@ extern LIBSHIBOKEN_API int PepRuntime_38_flag;
/*****************************************************************************
*
+ * Runtime support for Python 3.12 incompatibility
+ *
+ */
+
+LIBSHIBOKEN_API PyObject *PepType_GetDict(PyTypeObject *type);
+
+// This function does not exist as PyType_SetDict. But because tp_dict
+// is no longer considered to be accessible, we treat it as such.
+LIBSHIBOKEN_API int PepType_SetDict(PyTypeObject *type, PyObject *dict);
+
+LIBSHIBOKEN_API void *PepType_GetSlot(PyTypeObject *type, int aSlot);
+
+/*****************************************************************************
+ *
* Module Initialization
*
*/
diff --git a/sources/shiboken6/libshiboken/pep384impl_doc.rst b/sources/shiboken6/libshiboken/pep384impl_doc.rst
deleted file mode 100644
index 9ee74a26c..000000000
--- a/sources/shiboken6/libshiboken/pep384impl_doc.rst
+++ /dev/null
@@ -1,704 +0,0 @@
-****************************************
-The Transition To The Limited Python API
-****************************************
-
-
-Foreword
-========
-
-Python supports a limited API that restricts access to certain structures.
-Besides eliminating whole modules and all functions and macros which names
-start with an
-underscore, the most drastic restriction is the removal of normal type object
-declarations.
-
-For details about the eliminated modules and functions, please see the
-`PEP 384`_ page for reference.
-
-
-.. _`PEP 384`: https://www.python.org/dev/peps/pep-0384/
-
-
-
-Changed Modules
-===============
-
-All changed module's include files are listed with the changed functions here.
-As a general rule, it was tried to keep the changes to a minimum diff.
-Macros which are not available were changed to functions with the same name
-if possible. Completely removed names ``Py{name}`` were re-implemented as ``Pep{name}``.
-
-
-memoryobject.h
---------------
-
-The buffer protocol was completely removed. We redefined all the structures
-and methods, because PySide uses that. This is an exception to the limited API
-that we have to check ourselves. The code is extracted in bufferprocs_py37.h .
-This is related to the following:
-
-
-abstract.h
-----------
-
-This belongs to the buffer protocol like memoryobject.h .
-As replacement for ``Py_buffer`` we defined ``Pep_buffer`` and several other
-internal macros.
-
-The version is checked by hand, and the version number must be updated only
-if the implementation does not change. Otherwise, we need to write version
-dependent code paths.
-
-It is questionable if it is worthwhile to continue using the buffer protocol
-or if we should try to get rid of ``Pep_buffer``, completely.
-
-
-pydebug.h
----------
-
-We have no direct access to ``Py_VerboseFlag`` because debugging is not
-supported. We redefined it as macro ``Py_VerboseFlag`` which calls ``Pep_VerboseFlag``.
-
-
-unicodeobject.h
----------------
-
-The macro ``PyUnicode_GET_SIZE`` was removed and replaced by ``PepUnicode_GetLength``
-which evaluates to ``PyUnicode_GetSize`` for Python 2 and ``PyUnicode_GetLength`` for Python 3.
-Since Python 3.3, ``PyUnicode_GetSize`` would have the bad side effect of requiring the GIL!
-
-Function ``_PyUnicode_AsString`` is unavailable and was replaced by a macro
-that calls ``_PepUnicode_AsString``. The implementation was a bit involved,
-and it would be better to change the code and replace this function.
-
-
-bytesobject.h
--------------
-
-The macros ``PyBytes_AS_STRING`` and ``PyBytes_GET_SIZE`` were redefined to call
-the according functions.
-
-
-floatobject.h
--------------
-
-``PyFloat_AS_DOUBLE`` now calls ``PyFloat_AsDouble``.
-
-
-tupleobject.h
--------------
-
-``PyTuple_GET_ITEM``, ``PyTuple_SET_ITEM`` and ``PyTuple_GET_SIZE`` were redefined as
-function calls.
-
-
-listobject.h
-------------
-
-``PyList_GET_ITEM``, ``PyList_SET_ITEM`` and ``PyList_GET_SIZE`` were redefined as
-function calls.
-
-
-dictobject.h
-------------
-
-``PyDict_GetItem`` also exists in a ``PyDict_GetItemWithError`` version that does
-not suppress errors. This suppression has the side effect of touching global
-structures. This function exists in Python 2 only since Python 2.7.12 and has
-a different name. We simply implemented the function.
-Needed to avoid the GIL when accessing dictionaries.
-
-
-methodobject.h
---------------
-
-``PyCFunction_GET_FUNCTION``, ``PyCFunction_GET_SELF`` and ``PyCFunction_GET_FLAGS``
-were redefined as function calls.
-
-Direct access to the methoddef structure is not available, and we defined
-``PepCFunction_GET_NAMESTR`` as accessor for name strings.
-
-
-pythonrun.h
------------
-
-The simple function ``PyRun_String`` is not available. It was re-implemented
-in a simplified version for the signature module.
-
-
-funcobject.h
-------------
-
-The definitions of funcobject.h are completely missing, although there
-are extra ``#ifdef`` conditional defines inside, too. This suggests that the exclusion
-was unintended.
-
-We therefore redefined ``PyFunctionObject`` as an opaque type.
-
-The missing macro ``PyFunction_Check`` was defined, and the macro
-``PyFunction_GET_CODE`` calls the according function.
-
-There is no equivalent for function name access, therefore we introduced
-``PepFunction_GetName`` either as a function or as a macro.
-
-*TODO: We should fix funcobject.h*
-
-
-classobject.h
--------------
-
-Classobject is also completely not imported, instead of defining an opaque type.
-
-We defined the missing functions ``PyMethod_New``, ``PyMethod_Function`` and
-``PyMethod_Self`` and also redefined ``PyMethod_GET_SELF`` and
-``PyMethod_GET_FUNCTION`` as calls to these functions.
-
-*TODO: We should fix classobject.h*
-
-
-code.h
-------
-
-The whole code.c code is gone, although it may make sense to
-define some minimum accessibility. This will be clarified on
-`Python-Dev`_. We needed access to code objects and defined the missing
-PepCode_GET_FLAGS and PepCode_GET_ARGCOUNT either as function or macro.
-We further added the missing flags, although few are used:
-
-``CO_OPTIMIZED`` ``CO_NEWLOCALS`` ``CO_VARARGS`` ``CO_VARKEYWORDS`` ``CO_NESTED``
-``CO_GENERATOR``
-
-*TODO: We should maybe fix code.h*
-
-.. _`Python-Dev`: https://mail.python.org/mailman/listinfo/python-dev
-
-datetime.h
-----------
-
-The DateTime module is explicitly not included in the limited API.
-We defined all the needed functions but called them via Python instead
-of direct call macros. This has a slight performance impact.
-
-The performance could be easily improved by providing an interface
-that fetches all attributes at once, instead of going through the object
-protocol every time.
-
-The re-defined macros and methods are::
-
- PyDateTime_GET_YEAR
- PyDateTime_GET_MONTH
- PyDateTime_GET_DAY
- PyDateTime_DATE_GET_HOUR
- PyDateTime_DATE_GET_MINUTE
- PyDateTime_DATE_GET_SECOND
- PyDateTime_DATE_GET_MICROSECOND
- PyDateTime_DATE_GET_FOLD
- PyDateTime_TIME_GET_HOUR
- PyDateTime_TIME_GET_MINUTE
- PyDateTime_TIME_GET_SECOND
- PyDateTime_TIME_GET_MICROSECOND
- PyDateTime_TIME_GET_FOLD
-
- PyDate_Check
- PyDateTime_Check
- PyTime_Check
-
- PyDate_FromDate
- PyDateTime_FromDateAndTime
- PyTime_FromTime
-
-*XXX: We should maybe provide an optimized interface to datetime*
-
-
-object.h
---------
-
-The file object.h contains the ``PyTypeObject`` structure, which is supposed
-to be completely opaque. All access to types should be done through
-``PyType_GetSlot`` calls. Due to bugs and deficiencies in the limited API
-implementation, it was not possible to do that. Instead, we have defined
-a simplified structure for ``PyTypeObject`` that has only the fields that
-are used in PySide.
-
-We will explain later why and how this was done. Here is the reduced
-structure::
-
- typedef struct _typeobject {
- PyVarObject ob_base;
- const char *tp_name;
- Py_ssize_t tp_basicsize;
- void *X03; // Py_ssize_t tp_itemsize;
- void *X04; // destructor tp_dealloc;
- void *X05; // printfunc tp_print;
- void *X06; // getattrfunc tp_getattr;
- void *X07; // setattrfunc tp_setattr;
- void *X08; // PyAsyncMethods *tp_as_async;
- void *X09; // reprfunc tp_repr;
- void *X10; // PyNumberMethods *tp_as_number;
- void *X11; // PySequenceMethods *tp_as_sequence;
- void *X12; // PyMappingMethods *tp_as_mapping;
- void *X13; // hashfunc tp_hash;
- ternaryfunc tp_call;
- reprfunc tp_str;
- void *X16; // getattrofunc tp_getattro;
- void *X17; // setattrofunc tp_setattro;
- void *X18; // PyBufferProcs *tp_as_buffer;
- void *X19; // unsigned long tp_flags;
- void *X20; // const char *tp_doc;
- traverseproc tp_traverse;
- inquiry tp_clear;
- void *X23; // richcmpfunc tp_richcompare;
- Py_ssize_t tp_weaklistoffset;
- void *X25; // getiterfunc tp_iter;
- void *X26; // iternextfunc tp_iternext;
- struct PyMethodDef *tp_methods;
- void *X28; // struct PyMemberDef *tp_members;
- void *X29; // struct PyGetSetDef *tp_getset;
- struct _typeobject *tp_base;
- PyObject *tp_dict;
- descrgetfunc tp_descr_get;
- void *X33; // descrsetfunc tp_descr_set;
- Py_ssize_t tp_dictoffset;
- initproc tp_init;
- allocfunc tp_alloc;
- newfunc tp_new;
- freefunc tp_free;
- inquiry tp_is_gc; /* For PyObject_IS_GC */
- PyObject *tp_bases;
- PyObject *tp_mro; /* method resolution order */
- } PyTypeObject;
-
-Function ``PyIndex_Check`` had to be defined in an unwanted way due to
-a Python issue. See file pep384_issue33738.cpp .
-
-There are extension structures which have been isolated as special macros that
-dynamically compute the right offsets of the extended type structures:
-
-* ``PepType_SOTP`` for ``SbkObjectTypePrivate``
-* ``PepType_SETP`` for ``SbkEnumTypePrivate``
-* ``PepType_PFTP`` for ``PySideQFlagsTypePrivate``
-
-How these extension structures are used can best be seen by searching
-``PepType_{four}`` in the source.
-
-Due to the new heaptype interface, the names of certain types contain
-now the module name in the ``tp_name`` field. To have a compatible way
-to access simple type names as C string, ``PepType_GetNameStr`` has been
-written that skips over dotted name parts.
-
-Finally, the function ``_PyObject_Dump`` was excluded from the limited API.
-This is a useful debugging aid that we always want to have available,
-so it is added back, again. Anyway, we did not reimplement it, and so
-Windows is not supported.
-Therefore, a forgotten debugging call of this functions will break COIN. :-)
-
-
-Using The New Type API
-======================
-
-After converting everything but the object.h file, we were a little
-bit shocked: it suddenly was clear that we would have no more
-access to type objects, and even more scary that all types which we
-use have to be heap types, only!
-
-For PySide with its intense use of heap type extensions in various
-flavors, the situation looked quite unsolvable. In the end, it was
-nicely solved, but it took almost 3.5 months to get that right.
-
-Before we see how this is done, we will explain the differences
-between the APIs and their consequences.
-
-
-The Interface
--------------
-
-The old type API of Python knows static types and heap types.
-Static types are written down as a declaration of a ``PyTypeObject``
-structure with all its fields filled in. Here is for example
-the definition of the Python type ``object`` (Python 3.6)::
-
- PyTypeObject PyBaseObject_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "object", /* tp_name */
- sizeof(PyObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- object_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- object_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)_Py_HashPointer, /* tp_hash */
- 0, /* tp_call */
- object_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- object_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- object_methods, /* tp_methods */
- 0, /* tp_members */
- object_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- object_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- object_new, /* tp_new */
- PyObject_Del, /* tp_free */
- };
-
-We can write the same structure in form of a ``PyType_Spec`` structure,
-and there is even an incomplete tool *abitype.py* that does this conversion
-for us. With a few corrections, the result looks like this::
-
- static PyType_Slot PyBaseObject_Type_slots[] = {
- {Py_tp_dealloc, (void *)object_dealloc},
- {Py_tp_repr, (void *)object_repr},
- {Py_tp_hash, (void *)_Py_HashPointer},
- {Py_tp_str, (void *)object_str},
- {Py_tp_getattro, (void *)PyObject_GenericGetAttr},
- {Py_tp_setattro, (void *)PyObject_GenericSetAttr},
- {Py_tp_richcompare, (void *)object_richcompare},
- {Py_tp_methods, (void *)object_methods},
- {Py_tp_getset, (void *)object_getsets},
- {Py_tp_init, (void *)object_init},
- {Py_tp_alloc, (void *)PyType_GenericAlloc},
- {Py_tp_new, (void *)object_new},
- {Py_tp_free, (void *)PyObject_Del},
- {0, 0},
- };
- static PyType_Spec PyBaseObject_Type_spec = {
- "object",
- sizeof(PyObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- PyBaseObject_Type_slots,
- };
-
-This new structure is almost compatible with the old one, but there
-are some subtle differences.
-
-* The new types are generated in one step
-
-This seems to be no problem, but it was very much, due to the way the
-types were built in PySide. Types were assembled piece by piece, and
-finally the ``PyType_Ready`` function was called.
-
-With the new API, ``PyType_Ready`` is called already at the end of
-``PyType_FromSpec``, and that meant that the logic of type creation became
-completely turned upside down.
-
-* The new types are always heaptypes
-
-With the new type creation functions, it is no longer possible to
-create "normal" types. Instead, they all have to be allocated on the
-heap and garbage collected. The user should normally not recognize this.
-But type creation is more constrained, and you cannot create a subtype
-if the ``Py_TPFLAGS_BASETYPE`` is not set. This constraint was already
-violated by PySide and needed a quite profound fix.
-
-* The new types always need a module
-
-While this is not a problem per se, the above new type spec will not create
-a usable new type, but complain with::
-
- DeprecationWarning: builtin type object has no __module__ attribute
-
-But there are more problems:
-
-* The new types have unexpected defaults
-
-When fields are empty, you would usually assume that they stay empty.
-There are just a few corrections that ``PyType_Ready`` will do to a type.
-
-But there is the following clause in ``PyType_FromSpec`` that can give you
-many headaches::
-
- if (type->tp_dealloc == NULL) {
- /* It's a heap type, so needs the heap types' dealloc.
- subtype_dealloc will call the base type's tp_dealloc, if
- necessary. */
- type->tp_dealloc = subtype_dealloc;
- }
-
-In fact, before the move to the new API, the ``PyType_Ready`` function
-filled empty ``tp_dealloc`` fields with ``object_dealloc``. And the code
-that has been written with that in mind now becomes pretty wrong if suddenly
-``subtype_dealloc`` is used.
-
-The way out was to explicitly provide an ``object_dealloc`` function.
-This would then again impose a problem, because ``object_dealloc`` is not
-public. Writing our own version is easy, but it again needs access to
-type objects. But fortunately, we have broken this rule, already...
-
-
-* The new types are only partially allocated
-
-The structures used in ``PyType_FromSpec`` are almost all allocated,
-only the name field is static. This is no problem for types which are
-statically created once. But if you want to parameterize things and
-create multiple types with a single slots and spec definition, the name
-field that is used for tp_name must be allocated dynamically.
-This is misleading, since all the slots already are copies.
-
-* The new types don't support special offsets
-
-The special fields ``tp_weaklistoffset`` and ``tp_dictoffset`` are not supported
-by ``PyType_FromSpec``. Unfortunately the documentation does not tell you
-if you are allowed to set these fields manually after creating the type or not.
-We finally did it and it worked, but we are not sure about correctness.
-
-See basewrapper.cpp function ``SbkObject_TypeF()`` as the only reference to
-these fields in PySide. This single reference is absolutely necessary and
-very important, since all derived types invisibly inherit these two fields.
-
-
-Future Versions Of The Limited API
-==================================
-
-As we have seen, the current version of the limited API does a bit of
-cheating, because it uses parts of the data structure that should be
-an opaque type. At the moment, this works fine because the data is
-still way more compatible as it could be.
-
-But what if this is changed in the future?
-
-We know that the data structures are stable until Python 3.8 comes out.
-Until then, the small bugs and omissions will hopefully all be solved.
-Then it will be possible to replace the current small tricks by calls
-to ``PyType_GetSlot`` in the way things should be.
-
-At the very moment when the current assumptions about the data structure
-are no longer true, we will rewrite the direct attribute access with
-calls to ``PyType_GetSlot``. After that, no more changes will be necessary.
-
-
-Appendix A: The Transition To Simpler Types
-===========================================
-
-After all code had been converted to the limited API, there was a
-remaining problem with the ``PyHeapTypeObject``.
-
-Why a problem? Well, all the type structures in shiboken use
-special extra fields at the end of the heap type object. This
-currently enforces extra knowledge at compile time about how large the
-heap type object is. In a clean implementation, we would only use
-the ``PyTypeObject`` itself and access the fields *behind* the type
-by a pointer that is computed at runtime.
-
-
-Restricted PyTypeObject
------------------------
-
-Before we are going into details, let us motivate the existence of
-the restricted ``PyTypeObject``:
-
-Originally, we wanted to use ``PyTypeObject`` as an opaque type and
-restrict ourselves to only use the access function ``PyType_GetSlot``.
-This function allows access to all fields which are supported by
-the limited API.
-
-But this is a restriction, because we get no access to ``tp_dict``,
-which we need to support the signature extension. But we can work
-around that.
-
-The real restriction is that ``PyType_GetSlot`` only works for heap
-types. This makes the function quite useless, because we have
-no access to ``PyType_Type``, which is the most important type ``type``
-in Python. We need that for instance to compute the size of
-``PyHeapTypeObject`` dynamically.
-
-With much effort, it is possible to clone ``PyType_Type`` as a heap
-type. But due to a bug in the Pep 384 support, we need
-access to the ``nb_index`` field of a normal type. Cloning does not
-help because ``PyNumberMethods`` fields are *not* inherited.
-
-After we realized this dead end, we changed concept and did not
-use ``PyType_GetSlot`` at all (except in function ``copyNumberMethods``),
-but created a restricted ``PyTypeObject`` with only those fields
-defined that are needed in PySide.
-
-Is this breakage of the limited API? I don't think so. A special
-function runs on program startup that checks the correct position
-of the fields of ``PyTypeObject``, although a change in those fields is
-more than unlikely.
-The really crucial thing is to no longer use ``PyHeapTypeObject``
-explicitly because that *does* change its layout over time.
-
-
-Diversification
----------------
-
-There were multiple ``Sbk{something}`` structures which all used a "d" field
-for their private data. This made it not easy to find the right
-fields when switching between objects and types::
-
- struct LIBSHIBOKEN_API SbkObject
- {
- PyObject_HEAD
- PyObject *ob_dict;
- PyObject *weakreflist;
- SbkObjectPrivate *d;
- };
-
- struct LIBSHIBOKEN_API SbkObjectType
- {
- PyHeapTypeObject super;
- SbkObjectTypePrivate *d;
- };
-
-The first step was to rename the SbkObjectTypePrivate part from "d" to
-"sotp". It was chosen to be short but easy to remember as abbreviation
-of "SbkObjectTypePrivate", leading to::
-
- struct LIBSHIBOKEN_API SbkObjectType
- {
- PyHeapTypeObject super;
- SbkObjectTypePrivate *sotp;
- };
-
-After renaming, it was easier to do the following transformations.
-
-
-Abstraction
------------
-
-After renaming the type extension pointers to ``sotp``, I replaced
-them by function-like macros which did the special access *behind*
-the types, instead of those explicit fields. For instance, the
-expression::
-
- type->sotp->converter
-
-became::
-
- PepType_SOTP(type)->converter
-
-The macro expansion can be seen here::
-
- #define PepHeapType_SIZE \
- (reinterpret_cast<PyTypeObject *>(&PyType_Type)->tp_basicsize)
-
- #define _genericTypeExtender(etype) \
- (reinterpret_cast<char *>(etype) + PepHeapType_SIZE)
-
- #define PepType_SOTP(etype) \
- (*reinterpret_cast<SbkObjectTypePrivate **>(_genericTypeExtender(etype)))
-
-This looks complicated, but in the end there is only a single new
-indirection via ``PyType_Type``, which happens at runtime. This is the
-key to fulfil what Pep 384 wants to achieve: *No more version-dependent fields*.
-
-
-Simplification
---------------
-
-After all type extension fields were replaced by macro calls, we
-could remove the following version dependent re-definition of ``PyHeapTypeObject``
-::
-
- typedef struct _pyheaptypeobject {
- union {
- PyTypeObject ht_type;
- void *opaque[PY_HEAPTYPE_SIZE];
- };
- } PyHeapTypeObject;
-
-, and the version dependent structure::
-
- struct LIBSHIBOKEN_API SbkObjectType
- {
- PyHeapTypeObject super;
- SbkObjectTypePrivate *sotp;
- };
-
-could be removed. SbkObjectType remains as a (deprecated)
-type alias to PyTypeObject.
-
-
-Appendix B: Verification Of PyTypeObject
-========================================
-
-We have introduced a limited PyTypeObject in the same place
-as the original PyTypeObject, and now we need to prove that
-we are allowed to do so.
-
-When using the limited API as intended, then types are completely
-opaque, and access is only through ``PyType_FromSpec`` and (from
-version 3.5 upwards) through ``PyType_GetSlot``.
-
-Python then uses all the slot definitions in the type description
-and produces a regular heap type object.
-
-
-Unused Information
-------------------
-
-We know many things about types that are not explicitly said,
-but they are inherently clear:
-
-(a) The basic structure of a type is always the same, regardless
- if it is a static type or a heap type.
-
-(b) types are evolving very slowly, and a field is never replaced
- by another field with different semantics.
-
-Inherent rule (a) gives us the following information: If we calculate
-the offsets of the basic fields, then this info is also usable for non-heap
-types.
-
-The validation checks if rule (b) is still valid.
-
-
-How it Works
-------------
-
-The basic idea of the validation is to produce a new type using
-``PyType_FromSpec`` and to see where in the type structure these fields
-show up. So we build a ``PyType_Slot`` structure with all the fields we
-are using and make sure that these values are all unique in the
-type.
-
-Most fields are not interrogated by ``PyType_FromSpec``, and so we
-simply used some numeric value. Some fields are interpreted, like
-``tp_members``. This field must really be a ``PyMemberDef``. And there are
-``tp_base`` and ``tp_bases`` which have to be type objects and lists
-thereof. It was easiest to not produce these fields from scratch
-but use them from the ``type`` object ``PyType_Type``.
-
-Then one would think to write a function that searches the known
-values in the opaque type structure.
-
-But we can do better and use optimistically the observation (b):
-We simply use the restricted ``PyTypeObject`` structure and assume that
-every field lands exactly where we are awaiting it.
-
-And that is the whole proof: If we find all the disjoint values at
-the places where we expect them, then verification is done.
-
-
-About ``tp_dict``
------------------
-
-One word about the ``tp_dict`` field: This field is a bit special in
-the proof, since it does not appear in the spec and cannot easily
-be checked by ``type.__dict__`` because that creates a *dictproxy*
-object. So how do we prove that is really the right dict?
-
-We have to create that ``PyMethodDef`` structure anyway, and instead of
-leaving it empty, we insert a dummy function. Then we ask the
-``tp_dict`` field if it has the awaited object in it, and that's it!
-
-#EOT
diff --git a/sources/shiboken6/libshiboken/pyobjectholder.h b/sources/shiboken6/libshiboken/pyobjectholder.h
new file mode 100644
index 000000000..857748c2f
--- /dev/null
+++ b/sources/shiboken6/libshiboken/pyobjectholder.h
@@ -0,0 +1,86 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef PYOBJECTHOLDER_H
+#define PYOBJECTHOLDER_H
+
+#include "sbkpython.h"
+
+#include <cassert>
+#include <utility>
+
+namespace Shiboken
+{
+
+/// PyObjectHolder holds a PyObject pointer, keeping a reference decrementing
+/// its reference counter when destroyed. It makes sure to hold the GIL when
+/// releasing. It implements copy/move semantics and is mainly intended as a
+/// base class for functors holding a callable which can be passed around and
+/// stored in containers or moved from freely.
+/// For one-shot functors, release() can be invoked after the call.
+class PyObjectHolder
+{
+public:
+ PyObjectHolder() noexcept = default;
+
+ /// PyObjectHolder constructor.
+ /// \param pyobj A reference to a Python object
+ explicit PyObjectHolder(PyObject *pyObj) noexcept : m_pyObj(pyObj)
+ {
+ assert(pyObj != nullptr);
+ Py_INCREF(m_pyObj);
+ }
+
+ PyObjectHolder(const PyObjectHolder &o) noexcept : m_pyObj(o.m_pyObj)
+ {
+ Py_XINCREF(m_pyObj);
+ }
+
+ PyObjectHolder &operator=(const PyObjectHolder &o) noexcept
+ {
+ if (this != &o) {
+ m_pyObj = o.m_pyObj;
+ Py_XINCREF(m_pyObj);
+ }
+ return *this;
+ }
+
+ PyObjectHolder(PyObjectHolder &&o) noexcept : m_pyObj{std::exchange(o.m_pyObj, nullptr)} {}
+
+ PyObjectHolder &operator=(PyObjectHolder &&o) noexcept
+ {
+ m_pyObj = std::exchange(o.m_pyObj, nullptr);
+ return *this;
+ }
+
+ /// Decref the python reference
+ ~PyObjectHolder() { release(); }
+
+ [[nodiscard]] bool isNull() const { return m_pyObj == nullptr; }
+ [[nodiscard]] operator bool() const { return m_pyObj != nullptr; }
+
+ /// Returns the pointer of the Python object being held.
+ [[nodiscard]] PyObject *object() const { return m_pyObj; }
+ [[nodiscard]] operator PyObject *() const { return m_pyObj; }
+
+ [[nodiscard]] PyObject *operator->() { return m_pyObj; }
+
+protected:
+ void release()
+ {
+ if (m_pyObj != nullptr) {
+ assert(Py_IsInitialized());
+ auto gstate = PyGILState_Ensure();
+ Py_DECREF(m_pyObj);
+ PyGILState_Release(gstate);
+ m_pyObj = nullptr;
+ }
+ }
+
+private:
+ PyObject *m_pyObj = nullptr;
+};
+
+} // namespace Shiboken
+
+#endif // PYOBJECTHOLDER_H
diff --git a/sources/shiboken6/libshiboken/sbkarrayconverter.cpp b/sources/shiboken6/libshiboken/sbkarrayconverter.cpp
index 8af310a53..bcc3fb767 100644
--- a/sources/shiboken6/libshiboken/sbkarrayconverter.cpp
+++ b/sources/shiboken6/libshiboken/sbkarrayconverter.cpp
@@ -14,8 +14,7 @@
static SbkArrayConverter *ArrayTypeConverters[Shiboken::Conversions::SBK_ARRAY_IDX_SIZE] [2] = {};
-namespace Shiboken {
-namespace Conversions {
+namespace Shiboken::Conversions {
// Check whether Predicate is true for all elements of a sequence
template <class Predicate>
@@ -244,5 +243,4 @@ void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c)
ArrayTypeConverters[index][dimension - 1] = c;
}
-} // namespace Conversions
-} // namespace Shiboken
+} // namespace Shiboken::Conversions
diff --git a/sources/shiboken6/libshiboken/sbkarrayconverter.h b/sources/shiboken6/libshiboken/sbkarrayconverter.h
index 97bd8ac6f..f07cb1d70 100644
--- a/sources/shiboken6/libshiboken/sbkarrayconverter.h
+++ b/sources/shiboken6/libshiboken/sbkarrayconverter.h
@@ -11,8 +11,7 @@ extern "C" {
struct SbkArrayConverter;
}
-namespace Shiboken {
-namespace Conversions {
+namespace Shiboken::Conversions {
enum : int {
SBK_UNIMPLEMENTED_ARRAY_IDX,
@@ -132,7 +131,6 @@ void ArrayHandle<T>::destroy()
m_owned = false;
}
-} // namespace Conversions
-} // namespace Shiboken
+} // namespace Shiboken::Conversions
#endif // SBKARRAYCONVERTERS_H
diff --git a/sources/shiboken6/libshiboken/sbkarrayconverter_p.h b/sources/shiboken6/libshiboken/sbkarrayconverter_p.h
index db92e56af..63d03fb12 100644
--- a/sources/shiboken6/libshiboken/sbkarrayconverter_p.h
+++ b/sources/shiboken6/libshiboken/sbkarrayconverter_p.h
@@ -10,7 +10,7 @@
extern "C"
{
-typedef PythonToCppFunc (*IsArrayConvertibleToCppFunc)(PyObject *, int dim1, int dim2);
+using IsArrayConvertibleToCppFunc = PythonToCppFunc (*)(PyObject *, int dim1, int dim2);
/**
* \internal
* Private structure of SbkArrayConverter.
diff --git a/sources/shiboken6/libshiboken/sbkcontainer.cpp b/sources/shiboken6/libshiboken/sbkcontainer.cpp
index 13c9f1a29..7de1f03e6 100644
--- a/sources/shiboken6/libshiboken/sbkcontainer.cpp
+++ b/sources/shiboken6/libshiboken/sbkcontainer.cpp
@@ -3,14 +3,17 @@
#include "sbkcontainer.h"
#include "sbkstaticstrings.h"
+#include "autodecref.h"
namespace Shiboken
{
bool isOpaqueContainer(PyObject *o)
{
+ if (!o)
+ return false;
+ Shiboken::AutoDecRef tpDict(PepType_GetDict(o->ob_type));
return o != nullptr && o != Py_None
- && PyDict_Contains(o->ob_type->tp_dict,
- Shiboken::PyMagicName::opaque_container()) == 1;
+ && PyDict_Contains(tpDict.object(), Shiboken::PyMagicName::opaque_container()) == 1;
}
} // Shiboken
diff --git a/sources/shiboken6/libshiboken/sbkcontainer.h b/sources/shiboken6/libshiboken/sbkcontainer.h
index 22513d3a0..8ad5aadc6 100644
--- a/sources/shiboken6/libshiboken/sbkcontainer.h
+++ b/sources/shiboken6/libshiboken/sbkcontainer.h
@@ -63,7 +63,8 @@ public:
static PyObject *tpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
{
- auto *me = reinterpret_cast<ShibokenContainer *>(subtype->tp_alloc(subtype, 0));
+ allocfunc allocFunc = reinterpret_cast<allocfunc>(PepType_GetSlot(subtype, Py_tp_alloc));
+ auto *me = reinterpret_cast<ShibokenContainer *>(allocFunc(subtype, 0));
auto *d = new ShibokenSequenceContainerPrivate;
d->m_list = new SequenceContainer;
d->m_ownsList = true;
@@ -71,6 +72,13 @@ public:
return reinterpret_cast<PyObject *>(me);
}
+ static PyObject *tpNewInvalid(PyTypeObject * /* subtype */, PyObject * /* args */, PyObject * /* kwds */)
+ {
+ return PyErr_Format(PyExc_NotImplementedError,
+ "Opaque containers of type '%s' cannot be instantiated.",
+ typeid(SequenceContainer).name());
+ }
+
static int tpInit(PyObject * /* self */, PyObject * /* args */, PyObject * /* kwds */)
{
return 0;
@@ -83,7 +91,9 @@ public:
if (d->m_ownsList)
delete d->m_list;
delete d;
- Py_TYPE(pySelf)->tp_base->tp_free(self);
+ auto freeFunc = reinterpret_cast<freefunc>(PepType_GetSlot(Py_TYPE(pySelf)->tp_base,
+ Py_tp_free));
+ freeFunc(self);
}
static Py_ssize_t sqLen(PyObject *self)
@@ -94,11 +104,9 @@ public:
static PyObject *sqGetItem(PyObject *self, Py_ssize_t i)
{
auto *d = get(self);
- if (i < 0 || i >= Py_ssize_t(d->m_list->size())) {
- PyErr_SetString(PyExc_IndexError, "index out of bounds");
- return nullptr;
- }
- auto it = d->m_list->cbegin();
+ if (i < 0 || i >= Py_ssize_t(d->m_list->size()))
+ return PyErr_Format(PyExc_IndexError, "index out of bounds");
+ auto it = std::cbegin(*d->m_list);
std::advance(it, i);
return ShibokenContainerValueConverter<value_type>::convertValueToPython(*it);
}
@@ -110,7 +118,7 @@ public:
PyErr_SetString(PyExc_IndexError, "index out of bounds");
return -1;
}
- auto it = d->m_list->begin();
+ auto it = std::begin(*d->m_list);
std::advance(it, i);
OptionalValue value = ShibokenContainerValueConverter<value_type>::convertValueToCpp(pyArg);
if (!value.has_value())
@@ -122,14 +130,10 @@ public:
static PyObject *push_back(PyObject *self, PyObject *pyArg)
{
auto *d = get(self);
- if (!ShibokenContainerValueConverter<value_type>::checkValue(pyArg)) {
- PyErr_SetString(PyExc_TypeError, "wrong type passed to append.");
- return nullptr;
- }
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (!ShibokenContainerValueConverter<value_type>::checkValue(pyArg))
+ return PyErr_Format(PyExc_TypeError, "wrong type passed to append.");
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
OptionalValue value = ShibokenContainerValueConverter<value_type>::convertValueToCpp(pyArg);
if (!value.has_value())
@@ -141,14 +145,10 @@ public:
static PyObject *push_front(PyObject *self, PyObject *pyArg)
{
auto *d = get(self);
- if (!ShibokenContainerValueConverter<value_type>::checkValue(pyArg)) {
- PyErr_SetString(PyExc_TypeError, "wrong type passed to append.");
- return nullptr;
- }
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (!ShibokenContainerValueConverter<value_type>::checkValue(pyArg))
+ return PyErr_Format(PyExc_TypeError, "wrong type passed to append.");
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
OptionalValue value = ShibokenContainerValueConverter<value_type>::convertValueToCpp(pyArg);
if (!value.has_value())
@@ -160,10 +160,8 @@ public:
static PyObject *clear(PyObject *self)
{
auto *d = get(self);
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
d->m_list->clear();
Py_RETURN_NONE;
@@ -172,10 +170,8 @@ public:
static PyObject *pop_back(PyObject *self)
{
auto *d = get(self);
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
d->m_list->pop_back();
Py_RETURN_NONE;
@@ -184,10 +180,8 @@ public:
static PyObject *pop_front(PyObject *self)
{
auto *d = get(self);
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
d->m_list->pop_front();
Py_RETURN_NONE;
@@ -197,21 +191,16 @@ public:
static PyObject *reserve(PyObject *self, PyObject *pyArg)
{
auto *d = get(self);
- if (PyLong_Check(pyArg) == 0) {
- PyErr_SetString(PyExc_TypeError, "wrong type passed to reserve().");
- return nullptr;
- }
- if (d->m_const) {
- PyErr_SetString(PyExc_TypeError, msgModifyConstContainer);
- return nullptr;
- }
+ if (PyLong_Check(pyArg) == 0)
+ return PyErr_Format(PyExc_TypeError, "wrong type passed to reserve().");
+ if (d->m_const)
+ return PyErr_Format(PyExc_TypeError, msgModifyConstContainer);
if constexpr (ShibokenContainerHasReserve<SequenceContainer>::value) {
const Py_ssize_t size = PyLong_AsSsize_t(pyArg);
d->m_list->reserve(size);
} else {
- PyErr_SetString(PyExc_TypeError, "Container does not support reserve().");
- return nullptr;
+ return PyErr_Format(PyExc_TypeError, "Container does not support reserve().");
}
Py_RETURN_NONE;
diff --git a/sources/shiboken6/libshiboken/sbkconverter.cpp b/sources/shiboken6/libshiboken/sbkconverter.cpp
index 309810290..d6056f874 100644
--- a/sources/shiboken6/libshiboken/sbkconverter.cpp
+++ b/sources/shiboken6/libshiboken/sbkconverter.cpp
@@ -4,6 +4,7 @@
#include "sbkconverter.h"
#include "sbkconverter_p.h"
#include "sbkarrayconverter_p.h"
+#include "sbkmodule.h"
#include "basewrapper_p.h"
#include "bindingmanager.h"
#include "autodecref.h"
@@ -11,15 +12,18 @@
#include "voidptr.h"
#include <string>
+#include <cstring>
+#include <iostream>
#include <unordered_map>
+#include <map>
+#include <set>
static SbkConverter **PrimitiveTypeConverters;
using ConvertersMap = std::unordered_map<std::string, SbkConverter *>;
static ConvertersMap converters;
-namespace Shiboken {
-namespace Conversions {
+namespace Shiboken::Conversions {
void initArrayConverters();
@@ -72,6 +76,99 @@ void init()
initArrayConverters();
}
+static void dumpPyTypeObject(std::ostream &str, PyTypeObject *t)
+{
+ str << "\nPython type ";
+ if (t == nullptr) {
+ str << "<None>";
+ return;
+ }
+ str << '"' << t->tp_name << '"';
+ if (t->tp_base != nullptr && t->tp_base != &PyBaseObject_Type)
+ str << '(' << t->tp_base->tp_name << ')';
+}
+
+static void dumpSbkConverter(std::ostream &str, const SbkConverter *c)
+{
+ str << "SbkConverter " << static_cast<const void *>(c) << ": ";
+ if (c->pointerToPython != nullptr)
+ str << ", C++ pointer->Python";
+ if (c->copyToPython != nullptr)
+ str << ", copy->Python";
+ if (c->toCppPointerConversion.second != nullptr)
+ str << ", Python->C++ pointer";
+ if (!c->toCppConversions.empty())
+ str << ", " << c->toCppConversions.size() << " Python->C++ conversions";
+}
+
+// Less than operator for a PyTypeObject for dumping the converter map
+static bool pyTypeObjectLessThan(const PyTypeObject *t1, const PyTypeObject *t2)
+{
+ const bool isNull1 = t1 == nullptr;
+ const bool isNull2 = t2 == nullptr;
+ if (isNull1 || isNull2)
+ return isNull1 && !isNull2;
+ // Internal types (lower case) first
+ const bool isInternal1 = std::islower(t1->tp_name[0]);
+ const bool isInternal2 = std::islower(t2->tp_name[0]);
+ if (isInternal1 != isInternal2)
+ return !isInternal2;
+ return std::strcmp(t1->tp_name, t2->tp_name) < 0;
+}
+
+void dumpConverters()
+{
+ struct PyTypeObjectLess {
+
+ bool operator()(const PyTypeObject *t1, const PyTypeObject *t2) const {
+ return pyTypeObjectLessThan(t1, t2);
+ }
+ };
+
+ using StringSet = std::set<std::string>;
+ using SbkConverterNamesMap = std::unordered_map<SbkConverter *, StringSet>;
+ using PyTypeObjectConverterMap = std::map<PyTypeObject *, SbkConverterNamesMap,
+ PyTypeObjectLess>;
+
+ auto &str = std::cerr;
+
+ // Sort the entries by the associated PyTypeObjects and converters
+ PyTypeObjectConverterMap pyTypeObjectConverterMap;
+ for (const auto &converter : converters) {
+ auto *sbkConverter = converter.second;
+ auto *typeObject = sbkConverter->pythonType;
+ auto typeIt = pyTypeObjectConverterMap.find(typeObject);
+ if (typeIt == pyTypeObjectConverterMap.end())
+ typeIt = pyTypeObjectConverterMap.insert(std::make_pair(typeObject,
+ SbkConverterNamesMap{})).first;
+ SbkConverterNamesMap &sbkConverterMap = typeIt->second;
+ auto convIt = sbkConverterMap.find(sbkConverter);
+ if (convIt == sbkConverterMap.end())
+ convIt = sbkConverterMap.insert(std::make_pair(sbkConverter,
+ StringSet{})).first;
+ convIt->second.insert(converter.first);
+ }
+
+ for (const auto &tc : pyTypeObjectConverterMap) {
+ dumpPyTypeObject(str, tc.first);
+ str << ", " << tc.second.size() << " converter(s):\n";
+ for (const auto &cn : tc.second) {
+ str << " ";
+ dumpSbkConverter(str, cn.first);
+ str << ", " << cn.second.size() << " alias(es):";
+ int i = 0;
+ for (const auto &name : cn.second) {
+ if ((i++ % 5) == 0)
+ str << "\n ";
+ str << " \"" << name << '"';
+ }
+ str << '\n';
+ }
+ }
+
+ str << '\n';
+}
+
SbkConverter *createConverterObject(PyTypeObject *type,
PythonToCppFunc toCppPointerConvFunc,
IsConvertibleToCppFunc toCppPointerCheckFunc,
@@ -147,6 +244,13 @@ void addPythonToCppValueConversion(PyTypeObject *type,
addPythonToCppValueConversion(sotp->converter, pythonToCppFunc, isConvertibleToCppFunc);
}
+void addPythonToCppValueConversion(Shiboken::Module::TypeInitStruct typeStruct,
+ PythonToCppFunc pythonToCppFunc,
+ IsConvertibleToCppFunc isConvertibleToCppFunc)
+{
+ addPythonToCppValueConversion(typeStruct.type, pythonToCppFunc, isConvertibleToCppFunc);
+}
+
PyObject *pointerToPython(PyTypeObject *type, const void *cppIn)
{
auto *sotp = PepType_SOTP(type);
@@ -228,6 +332,11 @@ PythonToCppConversion pythonToCppPointerConversion(PyTypeObject *type, PyObject
return {};
}
+PythonToCppConversion pythonToCppPointerConversion(Module::TypeInitStruct typeStruct, PyObject *pyIn)
+{
+ return pythonToCppPointerConversion(typeStruct.type, pyIn);
+}
+
static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn)
{
assert(pyIn);
@@ -403,19 +512,34 @@ bool isImplicitConversion(PyTypeObject *type, PythonToCppFunc toCppFunc)
return toCppFunc != (*conv).second;
}
-void registerConverterName(SbkConverter *converter , const char *typeName)
+void registerConverterName(SbkConverter *converter, const char *typeName)
{
auto iter = converters.find(typeName);
if (iter == converters.end())
converters.insert(std::make_pair(typeName, converter));
}
+static std::string getRealTypeName(const char *name)
+{
+ std::string typeName(name);
+ auto size = typeName.size();
+ if (std::isalnum(typeName[size - 1]) == 0)
+ return typeName.substr(0, size - 1);
+ return typeName;
+}
+
SbkConverter *getConverter(const char *typeName)
{
- ConvertersMap::const_iterator it = converters.find(typeName);
+ auto it = converters.find(typeName);
+ if (it != converters.end())
+ return it->second;
+ // PYSIDE-2404: Did not find the name. Load the lazy classes
+ // which have this name and try again.
+ Shiboken::Module::loadLazyClassesWithName(getRealTypeName(typeName).c_str());
+ it = converters.find(typeName);
if (it != converters.end())
return it->second;
- if (Py_VerboseFlag > 0) {
+ if (Shiboken::pyVerbose() > 0) {
const std::string message =
std::string("Can't find type resolver for type '") + typeName + "'.";
PyErr_WarnEx(PyExc_RuntimeWarning, message.c_str(), 0);
@@ -677,7 +801,14 @@ PyTypeObject *getPythonTypeObject(const SbkConverter *converter)
PyTypeObject *getPythonTypeObject(const char *typeName)
{
- return getPythonTypeObject(getConverter(typeName));
+ auto *type = getPythonTypeObject(getConverter(typeName));
+ if (type == nullptr) {
+ // PYSIDE-2404: Did not find the name. Load the lazy classes
+ // which have this name and try again.
+ Shiboken::Module::loadLazyClassesWithName(getRealTypeName(typeName).c_str());
+ type = getPythonTypeObject(getConverter(typeName));
+ }
+ return type;
}
bool pythonTypeIsValueType(const SbkConverter *converter)
@@ -748,4 +879,4 @@ void SpecificConverter::toCpp(PyObject *pyIn, void *cppOut)
}
}
-} } // namespace Shiboken::Conversions
+} // namespace Shiboken::Conversions
diff --git a/sources/shiboken6/libshiboken/sbkconverter.h b/sources/shiboken6/libshiboken/sbkconverter.h
index 1428b90e2..0d68f3faf 100644
--- a/sources/shiboken6/libshiboken/sbkconverter.h
+++ b/sources/shiboken6/libshiboken/sbkconverter.h
@@ -5,9 +5,9 @@
#define SBK_CONVERTER_H
#include "sbkpython.h"
+#include "sbkmodule.h"
#include "shibokenmacros.h"
#include "sbkenum.h"
-#include "sbkenum_p.h"
#include "basewrapper_p.h"
#include <limits>
@@ -43,7 +43,7 @@ struct SbkArrayConverter;
*
* C++ -> Python
*/
-typedef PyObject *(*CppToPythonFunc)(const void *);
+using CppToPythonFunc = PyObject *(*)(const void *);
/**
* This function converts a Python object to a C++ value, it may be
@@ -56,7 +56,7 @@ typedef PyObject *(*CppToPythonFunc)(const void *);
*
* Python -> C++
*/
-typedef void (*PythonToCppFunc)(PyObject *,void *);
+using PythonToCppFunc = void (*)(PyObject *,void *);
/**
* Checks if the Python object passed in the argument is convertible to a
@@ -67,7 +67,7 @@ typedef void (*PythonToCppFunc)(PyObject *,void *);
*
* Python -> C++ ?
*/
-typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject *);
+using IsConvertibleToCppFunc = PythonToCppFunc (*)(PyObject *);
} // extern "C"
@@ -147,6 +147,9 @@ LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter *converter,
LIBSHIBOKEN_API void addPythonToCppValueConversion(PyTypeObject *type,
PythonToCppFunc pythonToCppFunc,
IsConvertibleToCppFunc isConvertibleToCppFunc);
+LIBSHIBOKEN_API void addPythonToCppValueConversion(Shiboken::Module::TypeInitStruct typeStruct,
+ PythonToCppFunc pythonToCppFunc,
+ IsConvertibleToCppFunc isConvertibleToCppFunc);
// C++ -> Python ---------------------------------------------------------------------------
@@ -204,6 +207,7 @@ struct PythonToCppConversion
*/
LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(PyTypeObject *type, PyObject *pyIn);
LIBSHIBOKEN_API PythonToCppConversion pythonToCppPointerConversion(PyTypeObject *type, PyObject *pyIn);
+LIBSHIBOKEN_API PythonToCppConversion pythonToCppPointerConversion(Module::TypeInitStruct typeStruct, PyObject *pyIn);
/**
* Returns a Python to C++ conversion function if the Python object is convertible to a C++ value.
@@ -410,7 +414,7 @@ template<> inline PyTypeObject *SbkType<std::nullptr_t>() { return Py_TYPE(&_Py_
#define SbkChar_Check(X) (PyNumber_Check(X) || Shiboken::String::checkChar(X))
struct PySideQFlagsType;
-struct PySideQFlagsTypePrivate
+struct SbkQFlagsTypePrivate
{
SbkConverter *converter;
};
diff --git a/sources/shiboken6/libshiboken/sbkconverter_p.h b/sources/shiboken6/libshiboken/sbkconverter_p.h
index 27126fbb1..5d8c1977a 100644
--- a/sources/shiboken6/libshiboken/sbkconverter_p.h
+++ b/sources/shiboken6/libshiboken/sbkconverter_p.h
@@ -278,7 +278,7 @@ struct Primitive<PY_LONG_LONG> : OnePrimitive<PY_LONG_LONG>
{
PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
if (OverFlowChecker<PY_LONG_LONG>::check(result, pyIn))
- PyErr_SetObject(PyExc_OverflowError, 0);
+ PyErr_SetObject(PyExc_OverflowError, nullptr);
*reinterpret_cast<PY_LONG_LONG * >(cppOut) = result;
}
static PythonToCppFunc isConvertible(PyObject *pyIn)
@@ -327,7 +327,7 @@ struct FloatPrimitive : TwoPrimitive<FLOAT>
}
static void toCpp(PyObject *pyIn, void *cppOut)
{
- *reinterpret_cast<FLOAT *>(cppOut) = FLOAT(PyLong_AsLong(pyIn));
+ *reinterpret_cast<FLOAT *>(cppOut) = FLOAT(PyLong_AsDouble(pyIn));
}
static PythonToCppFunc isConvertible(PyObject *pyIn)
{
@@ -524,13 +524,16 @@ struct Primitive<std::nullptr_t> : OnePrimitive<std::nullptr_t>
}
};
-namespace Shiboken {
-namespace Conversions {
+namespace Shiboken::Conversions {
+
SbkConverter *createConverterObject(PyTypeObject *type,
PythonToCppFunc toCppPointerConvFunc,
IsConvertibleToCppFunc toCppPointerCheckFunc,
CppToPythonFunc pointerToPythonFunc,
CppToPythonFunc copyToPythonFunc);
-} // namespace Conversions
-} // namespace Shiboken
+
+LIBSHIBOKEN_API void dumpConverters();
+
+} // namespace Shiboken::Conversions
+
#endif // SBK_CONVERTER_P_H
diff --git a/sources/shiboken6/libshiboken/sbkcppstring.cpp b/sources/shiboken6/libshiboken/sbkcppstring.cpp
index 42b09111c..8e8324f5e 100644
--- a/sources/shiboken6/libshiboken/sbkcppstring.cpp
+++ b/sources/shiboken6/libshiboken/sbkcppstring.cpp
@@ -12,6 +12,11 @@ PyObject *fromCppString(const std::string &value)
return PyUnicode_FromStringAndSize(value.data(), value.size());
}
+PyObject *fromCppStringView(std::string_view value)
+{
+ return PyUnicode_FromStringAndSize(value.data(), value.size());
+}
+
PyObject *fromCppWString(const std::wstring &value)
{
return PyUnicode_FromWideChar(value.data(), value.size());
diff --git a/sources/shiboken6/libshiboken/sbkcppstring.h b/sources/shiboken6/libshiboken/sbkcppstring.h
index f418ea8dd..7ffe11c75 100644
--- a/sources/shiboken6/libshiboken/sbkcppstring.h
+++ b/sources/shiboken6/libshiboken/sbkcppstring.h
@@ -8,10 +8,12 @@
#include "shibokenmacros.h"
#include <string>
+#include <string_view>
namespace Shiboken::String
{
LIBSHIBOKEN_API PyObject *fromCppString(const std::string &value);
+ LIBSHIBOKEN_API PyObject *fromCppStringView(std::string_view value);
LIBSHIBOKEN_API PyObject *fromCppWString(const std::wstring &value);
LIBSHIBOKEN_API void toCppString(PyObject *str, std::string *value);
LIBSHIBOKEN_API void toCppWString(PyObject *str, std::wstring *value);
diff --git a/sources/shiboken6/libshiboken/sbkcpptonumpy.cpp b/sources/shiboken6/libshiboken/sbkcpptonumpy.cpp
new file mode 100644
index 000000000..44e900f01
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbkcpptonumpy.cpp
@@ -0,0 +1,67 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+// included by sbknumpy.cpp
+
+namespace Shiboken::Numpy {
+
+#ifdef HAVE_NUMPY
+
+// Helper to create a 1-dimensional numpy array
+template <class Type>
+static PyObject *_createArray1(Py_ssize_t size, int numpyType, const Type *data)
+{
+ const npy_intp dims[1] = {size};
+ PyObject *result = PyArray_EMPTY(1, dims, numpyType, 0);
+ auto *array = reinterpret_cast<PyArrayObject *>(result);
+ auto *rawTargetData = PyArray_DATA(array);
+ auto *targetData = reinterpret_cast<Type *>(rawTargetData);
+ std::copy(data, data + size, targetData);
+ return result;
+}
+
+PyObject *createByteArray1(Py_ssize_t size, const uint8_t *data)
+{
+ return _createArray1(size, NPY_BYTE, data);
+}
+
+PyObject *createDoubleArray1(Py_ssize_t size, const double *data)
+{
+ return _createArray1(size, NPY_DOUBLE, data);
+}
+
+PyObject *createFloatArray1(Py_ssize_t size, const float *data)
+{
+ return _createArray1(size, NPY_FLOAT, data);
+}
+
+PyObject *createIntArray1(Py_ssize_t size, const int *data)
+{
+ return _createArray1(size, NPY_INT, data);
+}
+
+#else // HAVE_NUMPY
+
+PyObject *createByteArray1(Py_ssize_t, const uint8_t *)
+{
+ return Py_None;
+}
+
+PyObject *createDoubleArray1(Py_ssize_t, const double *)
+{
+ return Py_None;
+}
+
+PyObject *createFloatArray1(Py_ssize_t, const float *)
+{
+ return Py_None;
+}
+
+PyObject *createIntArray1(Py_ssize_t, const int *)
+{
+ return Py_None;
+}
+
+#endif // !HAVE_NUMPY
+
+} //namespace Shiboken::Numpy
diff --git a/sources/shiboken6/libshiboken/sbkcpptonumpy.h b/sources/shiboken6/libshiboken/sbkcpptonumpy.h
new file mode 100644
index 000000000..8b9b0cfd2
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbkcpptonumpy.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef SBKCPPTONUMPY_H
+#define SBKCPPTONUMPY_H
+
+#include <sbkpython.h>
+#include <shibokenmacros.h>
+
+#include <cstdint>
+
+namespace Shiboken::Numpy
+{
+
+/// Create a one-dimensional numpy array of type uint8/NPY_BYTE
+/// \param size Size
+/// \param data Data
+/// \return PyArrayObject
+LIBSHIBOKEN_API PyObject *createByteArray1(Py_ssize_t size, const uint8_t *data);
+
+/// Create a one-dimensional numpy array of type double/NPY_DOUBLE
+/// \param size Size
+/// \param data Data
+/// \return PyArrayObject
+LIBSHIBOKEN_API PyObject *createDoubleArray1(Py_ssize_t size, const double *data);
+
+/// Create a one-dimensional numpy array of type float/NPY_FLOAT
+/// \param size Size
+/// \param data Data
+/// \return PyArrayObject
+LIBSHIBOKEN_API PyObject *createFloatArray1(Py_ssize_t size, const float *data);
+
+/// Create a one-dimensional numpy array of type int/NPY_INT
+/// \param size Size
+/// \param data Data
+/// \return PyArrayObject
+LIBSHIBOKEN_API PyObject *createIntArray1(Py_ssize_t size, const int *data);
+
+} //namespace Shiboken::Numpy
+
+#endif // SBKCPPTONUMPY_H
diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp
index 3f432dcb2..d39369979 100644
--- a/sources/shiboken6/libshiboken/sbkenum.cpp
+++ b/sources/shiboken6/libshiboken/sbkenum.cpp
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "sbkenum.h"
-#include "sbkenum_p.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
@@ -16,389 +15,35 @@
#include <vector>
#include <sstream>
-#define SbkEnumType_Check(o) (Py_TYPE(Py_TYPE(o)) == SbkEnumType_TypeF())
-using enum_func = PyObject *(*)(PyObject *, PyObject *);
-
using namespace Shiboken;
extern "C"
{
-// forward
-struct lastEnumCreated;
-
-// forward
-static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
- const char *name,
- PyTypeObject *enumType,
- PyTypeObject *flagsType);
-
struct SbkEnumType
{
PyTypeObject type;
};
-static void cleanupEnumTypes();
-
-struct SbkEnumObject
-{
- PyObject_HEAD
- long ob_value;
- PyObject *ob_name;
-};
-
-static PyTypeObject *SbkEnum_TypeF(); // forward
-
-static PyObject *SbkEnumObject_repr(PyObject *self)
-{
- const SbkEnumObject *enumObj = reinterpret_cast<SbkEnumObject *>(self);
- auto name = Py_TYPE(self)->tp_name;
- if (enumObj->ob_name) {
- return String::fromFormat("%s.%s", name, PyBytes_AS_STRING(enumObj->ob_name));
- }
- return String::fromFormat("%s(%ld)", name, enumObj->ob_value);
-}
-
-static PyObject *SbkEnumObject_name(PyObject *self, void *)
-{
- auto *enum_self = reinterpret_cast<SbkEnumObject *>(self);
-
- if (enum_self->ob_name == nullptr)
- Py_RETURN_NONE;
-
- Py_INCREF(enum_self->ob_name);
- return enum_self->ob_name;
-}
-
-static PyObject *SbkEnum_tp_new(PyTypeObject *type, PyObject *args, PyObject *)
-{
- long itemValue = 0;
- if (!PyArg_ParseTuple(args, "|l:__new__", &itemValue))
- return nullptr;
-
- if (type == SbkEnum_TypeF()) {
- PyErr_Format(PyExc_TypeError, "You cannot use %s directly", type->tp_name);
- return nullptr;
- }
-
- SbkEnumObject *self = PyObject_New(SbkEnumObject, type);
- if (!self)
- return nullptr;
- self->ob_value = itemValue;
- AutoDecRef item(Enum::getEnumItemFromValue(type, itemValue));
- self->ob_name = item.object() ? SbkEnumObject_name(item, nullptr) : nullptr;
- return reinterpret_cast<PyObject *>(self);
-}
-
-static const char *SbkEnum_SignatureStrings[] = {
- "Shiboken.Enum(self,itemValue:int=0)",
- nullptr}; // Sentinel
-
-static void enum_object_dealloc(PyObject *ob)
-{
- auto *self = reinterpret_cast<SbkEnumObject *>(ob);
- Py_XDECREF(self->ob_name);
- Sbk_object_dealloc(ob);
-}
-
-static PyObject *_enum_op(enum_func f, PyObject *a, PyObject *b) {
- PyObject *valA = a;
- PyObject *valB = b;
- PyObject *result = nullptr;
- bool enumA = false;
- bool enumB = false;
-
- // We are not allowing floats
- if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) {
- // Check if both variables are SbkEnumObject
- if (SbkEnumType_Check(valA)) {
- valA = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valA)->ob_value);
- enumA = true;
- }
- if (SbkEnumType_Check(valB)) {
- valB = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valB)->ob_value);
- enumB = true;
- }
- }
-
- // Without an enum we are not supporting the operation
- if (!(enumA || enumB)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- result = f(valA, valB);
-
- // Decreasing the reference of the used variables a and b.
- if (enumA)
- Py_DECREF(valA);
- if (enumB)
- Py_DECREF(valB);
- return result;
-}
-
-/* Notes:
- * On Py3k land we use long type when using integer numbers. However, on older
- * versions of Python (version 2) we need to convert it to int type,
- * respectively.
- *
- * Thus calling PyLong_FromLong() will result in calling PyLong_FromLong in
- * Py3k.
- */
-static PyObject *enum_int(PyObject *v)
-{
- return PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(v)->ob_value);
-}
-
-static PyObject *enum_and(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_And, self, b);
-}
-
-static PyObject *enum_or(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_Or, self, b);
-}
-
-static PyObject *enum_xor(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_Xor, self, b);
-}
-
-static int enum_bool(PyObject *v)
-{
- return (reinterpret_cast<SbkEnumObject *>(v)->ob_value > 0);
-}
-
-static PyObject *enum_add(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Add, self, v);
-}
-
-static PyObject *enum_subtract(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Subtract, self, v);
-}
-
-static PyObject *enum_multiply(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Multiply, self, v);
-}
-
-static PyObject *enum_richcompare(PyObject *self, PyObject *other, int op)
-{
- PyObject *valA = self;
- PyObject *valB = other;
- PyObject *result = nullptr;
- bool enumA = false;
- bool enumB = false;
-
- // We are not allowing floats
- if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) {
-
- // Check if both variables are SbkEnumObject
- if (SbkEnumType_Check(valA)) {
- valA = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valA)->ob_value);
- enumA = true;
- }
- if (SbkEnumType_Check(valB)) {
- valB = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valB)->ob_value);
- enumB =true;
- }
- }
-
- // Without an enum we are not supporting the operation
- if (!(enumA || enumB)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- result = PyObject_RichCompare(valA, valB, op);
-
- // Decreasing the reference of the used variables a and b.
- if (enumA)
- Py_DECREF(valA);
- if (enumB)
- Py_DECREF(valB);
-
- return result;
-}
-
-static Py_hash_t enum_hash(PyObject *pyObj)
-{
- Py_hash_t val = reinterpret_cast<SbkEnumObject *>(pyObj)->ob_value;
- if (val == -1)
- val = -2;
- return val;
-}
-
-static PyGetSetDef SbkEnumGetSetList[] = {
- {const_cast<char *>("name"), SbkEnumObject_name, nullptr, nullptr, nullptr},
- {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
-};
-
-static void SbkEnumTypeDealloc(PyObject *pyObj);
-static PyTypeObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
-
-static PyGetSetDef SbkEnumType_getsetlist[] = {
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(Sbk_TypeGet___signature__),
- nullptr, nullptr, nullptr},
- {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
-};
-
-static PyType_Slot SbkEnumType_Type_slots[] = {
- {Py_tp_dealloc, reinterpret_cast<void *>(SbkEnumTypeDealloc)},
- {Py_tp_base, reinterpret_cast<void *>(&PyType_Type)},
- {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
- {Py_tp_new, reinterpret_cast<void *>(SbkEnumTypeTpNew)},
- {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
- {Py_tp_getset, reinterpret_cast<void *>(SbkEnumType_getsetlist)},
- {0, nullptr}
-};
-
-// PYSIDE-535: The tp_itemsize field is inherited and does not need to be set.
-// In PyPy, it _must_ not be set, because it would have the meaning that a
-// `__len__` field must be defined. Not doing so creates a hard-to-find crash.
-static PyType_Spec SbkEnumType_Type_spec = {
- "1:Shiboken.EnumMeta",
- 0,
- 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- SbkEnumType_Type_slots,
-};
-
-PyTypeObject *SbkEnumType_TypeF(void)
-{
- static auto *type = SbkType_FromSpec(&SbkEnumType_Type_spec);
- return type;
-}
-
-static void SbkEnumTypeDealloc(PyObject *pyObj)
-{
- auto *enumType = reinterpret_cast<SbkEnumType *>(pyObj);
- auto *setp = PepType_SETP(enumType);
-
- PyObject_GC_UnTrack(pyObj);
-#ifndef Py_LIMITED_API
-# if PY_VERSION_HEX >= 0x030A0000
- Py_TRASHCAN_BEGIN(pyObj, 1);
-# else
- Py_TRASHCAN_SAFE_BEGIN(pyObj);
-# endif
-#endif
- if (setp->converter)
- Conversions::deleteConverter(setp->converter);
- PepType_SETP_delete(enumType);
-#ifndef Py_LIMITED_API
-# if PY_VERSION_HEX >= 0x030A0000
- Py_TRASHCAN_END;
-# else
- Py_TRASHCAN_SAFE_END(pyObj);
-# endif
-#endif
- if (PepRuntime_38_flag) {
- // PYSIDE-939: Handling references correctly.
- // This was not needed before Python 3.8 (Python issue 35810)
- Py_DECREF(Py_TYPE(pyObj));
- }
-}
-
-PyTypeObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
-{
- init_enum();
- return PepType_Type_tp_new(metatype, args, kwds);
-}
-
-} // extern "C"
-
-///////////////////////////////////////////////////////////////
-//
-// PYSIDE-15: Pickling Support for Qt Enum objects
-// This works very well and fixes the issue.
-//
-extern "C" {
-
-static PyObject *enum_unpickler = nullptr;
-
-// Pickling: reduce the Qt Enum object
-static PyObject *enum___reduce__(PyObject *obj)
-{
- init_enum();
- return Py_BuildValue("O(Ni)",
- enum_unpickler,
- Py_BuildValue("s", Py_TYPE(obj)->tp_name),
- PyLong_AS_LONG(obj));
-}
-
-} // extern "C"
-
-namespace Shiboken { namespace Enum {
-
-// Unpickling: rebuild the Qt Enum object
-PyObject *unpickleEnum(PyObject *enum_class_name, PyObject *value)
-{
- AutoDecRef parts(PyObject_CallMethod(enum_class_name,
- "split", "s", "."));
- if (parts.isNull())
- return nullptr;
- PyObject *top_name = PyList_GetItem(parts, 0); // borrowed ref
- if (top_name == nullptr)
- return nullptr;
- PyObject *module = PyImport_GetModule(top_name);
- if (module == nullptr) {
- PyErr_Format(PyExc_ImportError, "could not import module %.200s",
- String::toCString(top_name));
- return nullptr;
- }
- AutoDecRef cur_thing(module);
- int len = PyList_Size(parts);
- for (int idx = 1; idx < len; ++idx) {
- PyObject *name = PyList_GetItem(parts, idx); // borrowed ref
- PyObject *thing = PyObject_GetAttr(cur_thing, name);
- if (thing == nullptr) {
- PyErr_Format(PyExc_ImportError, "could not import Qt Enum type %.200s",
- String::toCString(enum_class_name));
- return nullptr;
- }
- cur_thing.reset(thing);
- }
- PyObject *klass = cur_thing;
- return PyObject_CallFunctionObjArgs(klass, value, nullptr);
-}
-
-} // namespace Enum
-} // namespace Shiboken
-
-extern "C" {
-
// Initialization
static bool _init_enum()
{
AutoDecRef shibo(PyImport_ImportModule("shiboken6.Shiboken"));
- auto mod = shibo.object();
- // publish Shiboken.Enum so that the signature gets initialized
- if (PyObject_SetAttrString(mod, "Enum", reinterpret_cast<PyObject *>(SbkEnum_TypeF())) < 0)
- return false;
- if (InitSignatureStrings(SbkEnum_TypeF(), SbkEnum_SignatureStrings) < 0)
- return false;
- enum_unpickler = PyObject_GetAttrString(mod, "_unpickle_enum");
- if (enum_unpickler == nullptr)
- return false;
- return true;
+ return !shibo.isNull();
}
-static int useOldEnum = -1;
-
-static PyMethodDef SbkEnumObject_Methods[] = {
- {"__reduce__", reinterpret_cast<PyCFunction>(enum___reduce__),
- METH_NOARGS, nullptr},
- {nullptr, nullptr, 0, nullptr} // Sentinel
-};
-
+static PyObject *PyEnumModule{};
static PyObject *PyEnumMeta{};
static PyObject *PyEnum{};
static PyObject *PyIntEnum{};
static PyObject *PyFlag{};
static PyObject *PyIntFlag{};
+static PyObject *PyFlag_KEEP{};
+
+bool PyEnumMeta_Check(PyObject *ob)
+{
+ return Py_TYPE(ob) == reinterpret_cast<PyTypeObject *>(PyEnumMeta);
+}
PyTypeObject *getPyEnumMeta()
{
@@ -407,6 +52,7 @@ PyTypeObject *getPyEnumMeta()
static auto *mod = PyImport_ImportModule("enum");
if (mod) {
+ PyEnumModule = mod;
PyEnumMeta = PyObject_GetAttrString(mod, "EnumMeta");
if (PyEnumMeta && PyType_Check(PyEnumMeta))
PyEnum = PyObject_GetAttrString(mod, "Enum");
@@ -416,8 +62,12 @@ PyTypeObject *getPyEnumMeta()
PyFlag = PyObject_GetAttrString(mod, "Flag");
if (PyFlag && PyType_Check(PyFlag))
PyIntFlag = PyObject_GetAttrString(mod, "IntFlag");
- if (PyIntFlag && PyType_Check(PyIntFlag))
+ if (PyIntFlag && PyType_Check(PyIntFlag)) {
+ // KEEP is defined from Python 3.11 on.
+ PyFlag_KEEP = PyObject_GetAttrString(mod, "KEEP");
+ PyErr_Clear();
return reinterpret_cast<PyTypeObject *>(PyEnumMeta);
+ }
}
Py_FatalError("Python module 'enum' not found");
return nullptr;
@@ -425,23 +75,22 @@ PyTypeObject *getPyEnumMeta()
void init_enum()
{
- static bool is_initialized = false;
- if (is_initialized)
+ static bool isInitialized = false;
+ if (isInitialized)
return;
- if (!(is_initialized || enum_unpickler || _init_enum()))
- Py_FatalError("could not load enum pickling helper function");
- Py_AtExit(cleanupEnumTypes);
+ if (!(isInitialized || _init_enum()))
+ Py_FatalError("could not init enum");
// PYSIDE-1735: Determine whether we should use the old or the new enum implementation.
- static const char *envname = "PYSIDE63_OPTION_PYTHON_ENUM";
- const char *envsetting = getenv(envname);
- // I tried to use the save version getenv_s instead, but this function does not
- // exist on macOS. But this does no harm:
- // This variable has been set already by parser.py initialization.
- assert(envsetting);
- useOldEnum = strncmp(envsetting, "0", 10) == 0;
+ static PyObject *option = PySys_GetObject("pyside6_option_python_enum");
+ if (!option || !PyLong_Check(option)) {
+ PyErr_Clear();
+ option = PyLong_FromLong(1);
+ }
+ int ignoreOver{};
+ Enum::enumOption = PyLong_AsLongAndOverflow(option, &ignoreOver);
getPyEnumMeta();
- is_initialized = true;
+ isInitialized = true;
}
// PYSIDE-1735: Helper function supporting QEnum
@@ -453,8 +102,8 @@ int enumIsFlag(PyObject *ob_type)
if (metatype != reinterpret_cast<PyTypeObject *>(PyEnumMeta))
return -1;
auto *mro = reinterpret_cast<PyTypeObject *>(ob_type)->tp_mro;
- Py_ssize_t idx, n = PyTuple_GET_SIZE(mro);
- for (idx = 0; idx < n; idx++) {
+ const Py_ssize_t n = PyTuple_GET_SIZE(mro);
+ for (Py_ssize_t idx = 0; idx < n; ++idx) {
auto *sub_type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx));
if (sub_type == reinterpret_cast<PyTypeObject *>(PyFlag))
return 1;
@@ -462,84 +111,121 @@ int enumIsFlag(PyObject *ob_type)
return 0;
}
-} // extern "C"
-
+///////////////////////////////////////////////////////////////////////
+//
+// Support for Missing Values
+// ==========================
+//
+// Qt enums sometimes use undefined values in enums.
+// The enum module handles this by the option "KEEP" for Flag and
+// IntFlag. The handling of missing enum values is still strict.
+//
+// We changed that (also for compatibility with some competitor)
+// and provide a `_missing_` function that creates the missing value.
+//
+// The idea:
+// ---------
+// We cannot modify the already created class.
+// But we can create a one-element class with the new value and
+// pretend that this is the already existing class.
+//
+// We create each constant only once and keep the result in a dict
+// "_sbk_missing_". This is similar to a competitor's "_sip_missing_".
//
-///////////////////////////////////////////////////////////////
-
-namespace Shiboken {
-class DeclaredEnumTypes
+static PyObject *missing_func(PyObject * /* self */ , PyObject *args)
{
-public:
- struct EnumEntry
- {
- char *name; // full name as allocated. type->tp_name might be a substring.
- PyTypeObject *type;
- };
-
- DeclaredEnumTypes(const DeclaredEnumTypes &) = delete;
- DeclaredEnumTypes(DeclaredEnumTypes &&) = delete;
- DeclaredEnumTypes &operator=(const DeclaredEnumTypes &) = delete;
- DeclaredEnumTypes &operator=(DeclaredEnumTypes &&) = delete;
-
- DeclaredEnumTypes();
- ~DeclaredEnumTypes();
- static DeclaredEnumTypes &instance();
- void addEnumType(const EnumEntry &e) { m_enumTypes.push_back(e); }
-
- void cleanup();
-
-private:
- std::vector<EnumEntry> m_enumTypes;
+ // In order to relax matters to be more compatible with C++, we need
+ // to create a pseudo-member with that value.
+ static auto *const _sbk_missing = Shiboken::String::createStaticString("_sbk_missing_");
+ static auto *const _name = Shiboken::String::createStaticString("__name__");
+ static auto *const _mro = Shiboken::String::createStaticString("__mro__");
+ static auto *const _class = Shiboken::String::createStaticString("__class__");
+
+ PyObject *klass{}, *value{};
+ if (!PyArg_UnpackTuple(args, "missing", 2, 2, &klass, &value))
+ Py_RETURN_NONE;
+ if (!PyLong_Check(value))
+ Py_RETURN_NONE;
+ auto *type = reinterpret_cast<PyTypeObject *>(klass);
+ AutoDecRef tpDict(PepType_GetDict(type));
+ auto *sbk_missing = PyDict_GetItem(tpDict.object(), _sbk_missing);
+ if (!sbk_missing) {
+ sbk_missing = PyDict_New();
+ PyDict_SetItem(tpDict.object(), _sbk_missing, sbk_missing);
+ }
+ // See if the value is already in the dict.
+ AutoDecRef val_str(PyObject_CallMethod(value, "__str__", nullptr));
+ auto *ret = PyDict_GetItem(sbk_missing, val_str);
+ if (ret) {
+ Py_INCREF(ret);
+ return ret;
+ }
+ // No, we must create a new object and insert it into the dict.
+ AutoDecRef cls_name(PyObject_GetAttr(klass, _name));
+ AutoDecRef mro(PyObject_GetAttr(klass, _mro));
+ auto *baseClass(PyTuple_GetItem(mro, 1));
+ AutoDecRef param(PyDict_New());
+ PyDict_SetItem(param, val_str, value);
+ AutoDecRef fake(PyObject_CallFunctionObjArgs(baseClass, cls_name.object(), param.object(),
+ nullptr));
+ ret = PyObject_GetAttr(fake, val_str);
+ PyDict_SetItem(sbk_missing, val_str, ret);
+ // Now the real fake: Pretend that the type is our original type!
+ PyObject_SetAttr(ret, _class, klass);
+ return ret;
+}
+
+static struct PyMethodDef dummy_methods[] = {
+ {"_missing_", reinterpret_cast<PyCFunction>(missing_func), METH_VARARGS|METH_STATIC, nullptr},
+ {nullptr, nullptr, 0, nullptr}
+};
+
+static PyType_Slot dummy_slots[] = {
+ {Py_tp_base, reinterpret_cast<void *>(&PyType_Type)},
+ {Py_tp_methods, reinterpret_cast<void *>(dummy_methods)},
+ {0, nullptr}
};
-namespace Enum {
+static PyType_Spec dummy_spec = {
+ "1:builtins.EnumType",
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ dummy_slots,
+};
-// forward
-static PyObject *newItemOld(PyTypeObject *enumType, long itemValue, const char *itemName);
+static PyObject *create_missing_func(PyObject *klass)
+{
+ // When creating the class, memorize it in the missing function by
+ // a partial function argument.
+ static auto *const type = SbkType_FromSpec(&dummy_spec);
+ static auto *const obType = reinterpret_cast<PyObject *>(type);
+ static auto *const _missing = Shiboken::String::createStaticString("_missing_");
+ static auto *const func = PyObject_GetAttr(obType, _missing);
+ static auto *const partial = Pep_GetPartialFunction();
+ return PyObject_CallFunctionObjArgs(partial, func, klass, nullptr);
+}
+//
+////////////////////////////////////////////////////////////////////////
-// forward
-static PyTypeObject * newTypeWithNameOld(const char *name,
- const char *cppName,
- PyTypeObject *numbers_fromFlag);
+} // extern "C"
+
+namespace Shiboken::Enum {
+
+int enumOption{};
bool check(PyObject *pyObj)
{
init_enum();
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF();
-
static PyTypeObject *meta = getPyEnumMeta();
return Py_TYPE(Py_TYPE(pyObj)) == reinterpret_cast<PyTypeObject *>(meta);
}
-static PyObject *getEnumItemFromValueOld(PyTypeObject *enumType, long itemValue)
-{
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- PyObject *values = PyDict_GetItem(enumType->tp_dict, PyName::values());
- if (values == nullptr)
- return nullptr;
-
- while (PyDict_Next(values, &pos, &key, &value)) {
- auto *obj = reinterpret_cast<SbkEnumObject *>(value);
- if (obj->ob_value == itemValue) {
- Py_INCREF(value);
- return value;
- }
- }
- return nullptr;
-}
-
-PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue)
+PyObject *getEnumItemFromValue(PyTypeObject *enumType, EnumValueType itemValue)
{
init_enum();
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return getEnumItemFromValueOld(enumType, itemValue);
auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
AutoDecRef val2members(PyObject_GetAttrString(obEnumType, "_value2member_map_"));
@@ -547,467 +233,220 @@ PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue)
PyErr_Clear();
return nullptr;
}
- AutoDecRef ob_value(PyLong_FromLong(itemValue));
+ AutoDecRef ob_value(PyLong_FromLongLong(itemValue));
auto *result = PyDict_GetItem(val2members, ob_value);
Py_XINCREF(result);
return result;
}
-static PyTypeObject *createEnum(const char *fullName, const char *cppName,
- PyTypeObject *flagsType)
+PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
+ const char *itemName)
{
init_enum();
- PyTypeObject *enumType = newTypeWithNameOld(fullName, cppName, flagsType);
- if (PyType_Ready(enumType) < 0) {
- Py_XDECREF(enumType);
- return nullptr;
- }
- return enumType;
-}
-PyTypeObject *createGlobalEnum(PyObject *module, const char *name, const char *fullName,
- const char *cppName, PyTypeObject *flagsType)
-{
- PyTypeObject *enumType = createEnum(fullName, cppName, flagsType);
- if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- flagsType = recordCurrentEnum(module, name, enumType, flagsType);
- if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType),
- reinterpret_cast<PyObject *>(flagsType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- return enumType;
-}
+ auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
+ if (!itemName)
+ return PyObject_CallFunction(obEnumType, "L", itemValue);
-PyTypeObject *createScopedEnum(PyTypeObject *scope, const char *name, const char *fullName,
- const char *cppName, PyTypeObject *flagsType)
-{
- PyTypeObject *enumType = createEnum(fullName, cppName, flagsType);
- if (enumType && PyDict_SetItemString(scope->tp_dict, name,
- reinterpret_cast<PyObject *>(enumType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- auto *obScope = reinterpret_cast<PyObject *>(scope);
- flagsType = recordCurrentEnum(obScope, name, enumType, flagsType);
- if (flagsType && PyDict_SetItemString(scope->tp_dict,
- PepType_GetNameStr(flagsType),
- reinterpret_cast<PyObject *>(flagsType)) < 0) {
- Py_DECREF(enumType);
+ static PyObject *const _member_map_ = String::createStaticString("_member_map_");
+ AutoDecRef tpDict(PepType_GetDict(enumType));
+ auto *member_map = PyDict_GetItem(tpDict.object(), _member_map_);
+ if (!(member_map && PyDict_Check(member_map)))
return nullptr;
- }
- return enumType;
+ auto *result = PyDict_GetItemString(member_map, itemName);
+ Py_XINCREF(result);
+ return result;
}
-static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue)
+EnumValueType getValue(PyObject *enumItem)
{
init_enum();
- PyObject *enumItem = newItemOld(enumType, itemValue, itemName);
- if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) {
- Py_DECREF(enumItem);
- return nullptr;
- }
- return enumItem;
-}
-bool createGlobalEnumItem(PyTypeObject *enumType, PyObject *module, const char *itemName, long itemValue)
-{
- PyObject *enumItem = createEnumItem(enumType, itemName, itemValue);
- if (!enumItem)
- return false;
- int ok = useOldEnum ? PyModule_AddObject(module, itemName, enumItem) : true;
- Py_DECREF(enumItem);
- return ok >= 0;
+ assert(Enum::check(enumItem));
+
+ AutoDecRef pyValue(PyObject_GetAttrString(enumItem, "value"));
+ return PyLong_AsLongLong(pyValue);
}
-bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
- const char *itemName, long itemValue)
+void setTypeConverter(PyTypeObject *type, SbkConverter *converter)
{
- PyObject *enumItem = createEnumItem(enumType, itemName, itemValue);
- if (!enumItem)
- return false;
- int ok = useOldEnum ? PyDict_SetItemString(scope->tp_dict, itemName, enumItem) : true;
- Py_DECREF(enumItem);
- return ok >= 0;
+ auto *enumType = reinterpret_cast<SbkEnumType *>(type);
+ PepType_SETP(enumType)->converter = converter;
}
-// This exists temporary as the old way to create an enum item.
-// For the public interface, we use a new function
-static PyObject *
-newItemOld(PyTypeObject *enumType, long itemValue, const char *itemName)
+static PyTypeObject *createEnumForPython(PyObject *scopeOrModule,
+ const char *fullName,
+ PyObject *pyEnumItems)
{
- bool newValue = true;
- SbkEnumObject *enumObj;
- if (!itemName) {
- enumObj = reinterpret_cast<SbkEnumObject *>(
- getEnumItemFromValue(enumType, itemValue));
- if (enumObj)
- return reinterpret_cast<PyObject *>(enumObj);
-
- newValue = false;
- }
-
- enumObj = PyObject_New(SbkEnumObject, enumType);
- if (!enumObj)
- return nullptr;
+ const char *colon = strchr(fullName, ':');
+ assert(colon);
+ int package_level = atoi(fullName);
+ const char *mod = colon + 1;
- enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : nullptr;
- enumObj->ob_value = itemValue;
-
- if (newValue) {
- auto dict = enumType->tp_dict; // Note: 'values' is borrowed
- PyObject *values = PyDict_GetItemWithError(dict, PyName::values());
- if (values == nullptr) {
- if (PyErr_Occurred())
- return nullptr;
- AutoDecRef new_values(values = PyDict_New());
- if (values == nullptr)
- return nullptr;
- if (PyDict_SetItem(dict, PyName::values(), values) < 0)
- return nullptr;
- }
- PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject *>(enumObj));
+ const char *qual = mod;
+ for (int idx = package_level; idx > 0; --idx) {
+ const char *dot = strchr(qual, '.');
+ if (!dot)
+ break;
+ qual = dot + 1;
+ }
+ int mlen = qual - mod - 1;
+ AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
+ AutoDecRef qualname(Shiboken::String::fromCString(qual));
+ const char *dot = strrchr(qual, '.');
+ AutoDecRef name(Shiboken::String::fromCString(dot ? dot + 1 : qual));
+
+ static PyObject *enumName = String::createStaticString("IntEnum");
+ if (PyType_Check(scopeOrModule)) {
+ // For global objects, we have no good solution, yet where to put the int info.
+ auto type = reinterpret_cast<PyTypeObject *>(scopeOrModule);
+ auto *sotp = PepType_SOTP(type);
+ if (!sotp->enumFlagsDict)
+ initEnumFlagsDict(type);
+ enumName = PyDict_GetItem(sotp->enumTypeDict, name);
}
- return reinterpret_cast<PyObject *>(enumObj);
-}
+ AutoDecRef PyEnumType(PyObject_GetAttr(PyEnumModule, enumName));
+ assert(PyEnumType.object());
+ bool isFlag = PyObject_IsSubclass(PyEnumType, PyFlag);
-PyObject *
-newItem(PyTypeObject *enumType, long itemValue, const char *itemName)
-{
- init_enum();
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return newItemOld(enumType, itemValue, itemName);
-
- if (!itemName) {
- //PyObject *enumObj = getEnumItemFromValue(enumType, itemValue);
- PyObject *enumObj = PyObject_CallFunction(reinterpret_cast<PyObject *>(enumType), "i", itemValue);
- //if (enumObj)
- return enumObj;
+ // See if we should use the Int versions of the types, again
+ bool useIntInheritance = Enum::enumOption & Enum::ENOPT_INHERIT_INT;
+ if (useIntInheritance) {
+ auto *surrogate = PyObject_IsSubclass(PyEnumType, PyFlag) ? PyIntFlag : PyIntEnum;
+ Py_INCREF(surrogate);
+ PyEnumType.reset(surrogate);
}
- return PyObject_GetAttrString(reinterpret_cast<PyObject *>(enumType), itemName);
-}
-} // namespace Shiboken
-} // namespace Enum
-
-static PyType_Slot SbkNewEnum_slots[] = {
- {Py_tp_repr, reinterpret_cast<void *>(SbkEnumObject_repr)},
- {Py_tp_str, reinterpret_cast<void *>(SbkEnumObject_repr)},
- {Py_tp_getset, reinterpret_cast<void *>(SbkEnumGetSetList)},
- {Py_tp_methods, reinterpret_cast<void *>(SbkEnumObject_Methods)},
- {Py_tp_new, reinterpret_cast<void *>(SbkEnum_tp_new)},
- {Py_nb_add, reinterpret_cast<void *>(enum_add)},
- {Py_nb_subtract, reinterpret_cast<void *>(enum_subtract)},
- {Py_nb_multiply, reinterpret_cast<void *>(enum_multiply)},
- {Py_nb_positive, reinterpret_cast<void *>(enum_int)},
- {Py_nb_bool, reinterpret_cast<void *>(enum_bool)},
- {Py_nb_and, reinterpret_cast<void *>(enum_and)},
- {Py_nb_xor, reinterpret_cast<void *>(enum_xor)},
- {Py_nb_or, reinterpret_cast<void *>(enum_or)},
- {Py_nb_int, reinterpret_cast<void *>(enum_int)},
- {Py_nb_index, reinterpret_cast<void *>(enum_int)},
- {Py_tp_richcompare, reinterpret_cast<void *>(enum_richcompare)},
- {Py_tp_hash, reinterpret_cast<void *>(enum_hash)},
- {Py_tp_dealloc, reinterpret_cast<void *>(enum_object_dealloc)},
- {0, nullptr}
-};
-static PyType_Spec SbkNewEnum_spec = {
- "1:Shiboken.Enum",
- sizeof(SbkEnumObject),
- 0,
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- SbkNewEnum_slots,
-};
+ // Walk the enumItemStrings and create a Python enum type.
+ auto *pyName = name.object();
-static PyTypeObject *SbkEnum_TypeF()
-{
- static auto type = SbkType_FromSpecWithMeta(&SbkNewEnum_spec, SbkEnumType_TypeF());
- return type;
-}
+ // We now create the new type. Since Python 3.11, we need to pass in
+ // `boundary=KEEP` because the default STRICT crashes on us.
+ // See QDir.Filter.Drives | QDir.Filter.Files
+ AutoDecRef callArgs(Py_BuildValue("(OO)", pyName, pyEnumItems));
+ AutoDecRef callDict(PyDict_New());
+ static PyObject *boundary = String::createStaticString("boundary");
+ if (PyFlag_KEEP)
+ PyDict_SetItem(callDict, boundary, PyFlag_KEEP);
+ auto *obNewType = PyObject_Call(PyEnumType, callArgs, callDict);
+ if (!obNewType || PyObject_SetAttr(scopeOrModule, pyName, obNewType) < 0)
+ return nullptr;
-namespace Shiboken { namespace Enum {
+ // For compatibility with Qt enums, provide a permissive missing method for (Int)?Enum.
+ if (!isFlag) {
+ bool supportMissing = !(Enum::enumOption & Enum::ENOPT_NO_MISSING);
+ if (supportMissing) {
+ AutoDecRef enum_missing(create_missing_func(obNewType));
+ PyObject_SetAttrString(obNewType, "_missing_", enum_missing);
+ }
+ }
-static void
-copyNumberMethods(PyTypeObject *flagsType,
- PyType_Slot number_slots[],
- int *pidx)
-{
- int idx = *pidx;
-#define PUT_SLOT(name) \
- number_slots[idx].slot = (name); \
- number_slots[idx].pfunc = PyType_GetSlot(flagsType, (name)); \
- ++idx;
-
- PUT_SLOT(Py_nb_absolute);
- PUT_SLOT(Py_nb_add);
- PUT_SLOT(Py_nb_and);
- PUT_SLOT(Py_nb_bool);
- PUT_SLOT(Py_nb_divmod);
- PUT_SLOT(Py_nb_float);
- PUT_SLOT(Py_nb_floor_divide);
- PUT_SLOT(Py_nb_index);
- PUT_SLOT(Py_nb_inplace_add);
- PUT_SLOT(Py_nb_inplace_and);
- PUT_SLOT(Py_nb_inplace_floor_divide);
- PUT_SLOT(Py_nb_inplace_lshift);
- PUT_SLOT(Py_nb_inplace_multiply);
- PUT_SLOT(Py_nb_inplace_or);
- PUT_SLOT(Py_nb_inplace_power);
- PUT_SLOT(Py_nb_inplace_remainder);
- PUT_SLOT(Py_nb_inplace_rshift);
- PUT_SLOT(Py_nb_inplace_subtract);
- PUT_SLOT(Py_nb_inplace_true_divide);
- PUT_SLOT(Py_nb_inplace_xor);
- PUT_SLOT(Py_nb_int);
- PUT_SLOT(Py_nb_invert);
- PUT_SLOT(Py_nb_lshift);
- PUT_SLOT(Py_nb_multiply);
- PUT_SLOT(Py_nb_negative);
- PUT_SLOT(Py_nb_or);
- PUT_SLOT(Py_nb_positive);
- PUT_SLOT(Py_nb_power);
- PUT_SLOT(Py_nb_remainder);
- PUT_SLOT(Py_nb_rshift);
- PUT_SLOT(Py_nb_subtract);
- PUT_SLOT(Py_nb_true_divide);
- PUT_SLOT(Py_nb_xor);
-#undef PUT_SLOT
- *pidx = idx;
-}
+ auto *newType = reinterpret_cast<PyTypeObject *>(obNewType);
+ PyObject_SetAttr(obNewType, PyMagicName::qualname(), qualname);
+ PyObject_SetAttr(obNewType, PyMagicName::module(), module);
-static PyTypeObject * newTypeWithNameOld(const char *name,
- const char *cppName,
- PyTypeObject *numbers_fromFlag)
-{
- // Careful: SbkType_FromSpec does not allocate the string.
- PyType_Slot newslots[99] = {}; // enough but not too big for the stack
- PyType_Spec newspec;
- DeclaredEnumTypes::EnumEntry entry{strdup(name), nullptr};
- newspec.name = entry.name; // Note that SbkType_FromSpec might use a substring.
- newspec.basicsize = SbkNewEnum_spec.basicsize;
- newspec.itemsize = SbkNewEnum_spec.itemsize;
- newspec.flags = SbkNewEnum_spec.flags;
- // we must append all the number methods, so rebuild everything:
- int idx = 0;
- while (SbkNewEnum_slots[idx].slot) {
- newslots[idx].slot = SbkNewEnum_slots[idx].slot;
- newslots[idx].pfunc = SbkNewEnum_slots[idx].pfunc;
- ++idx;
+ // See if we should re-introduce shortcuts in the enclosing object.
+ const bool useGlobalShortcut = (Enum::enumOption & Enum::ENOPT_GLOBAL_SHORTCUT) != 0;
+ const bool useScopedShortcut = (Enum::enumOption & Enum::ENOPT_SCOPED_SHORTCUT) != 0;
+ if (useGlobalShortcut || useScopedShortcut) {
+ // We have to use the iterator protokol because the values dict is a mappingproxy.
+ AutoDecRef values(PyObject_GetAttr(obNewType, PyMagicName::members()));
+ AutoDecRef mapIterator(PyObject_GetIter(values));
+ AutoDecRef mapKey{};
+ bool isModule = PyModule_Check(scopeOrModule);
+ while ((mapKey.reset(PyIter_Next(mapIterator))), mapKey.object()) {
+ if ((useGlobalShortcut && isModule) || (useScopedShortcut && !isModule)) {
+ AutoDecRef value(PyObject_GetItem(values, mapKey));
+ if (PyObject_SetAttr(scopeOrModule, mapKey, value) < 0)
+ return nullptr;
+ }
+ }
}
- if (numbers_fromFlag)
- copyNumberMethods(numbers_fromFlag, newslots, &idx);
- newspec.slots = newslots;
- AutoDecRef bases(PyTuple_New(1));
- static auto basetype = reinterpret_cast<PyObject *>(SbkEnum_TypeF());
- Py_INCREF(basetype);
- PyTuple_SetItem(bases, 0, basetype);
- auto *type = SbkType_FromSpecBasesMeta(&newspec, bases, SbkEnumType_TypeF());
- entry.type = type;
- auto *enumType = reinterpret_cast<SbkEnumType *>(type);
- auto *setp = PepType_SETP(enumType);
- setp->cppName = cppName;
- DeclaredEnumTypes::instance().addEnumType(entry);
- return entry.type;
+ return newType;
}
-// PySIDE-1735: This function is in the API and should be removed in 6.4 .
-// Python enums are created differently.
-PyTypeObject *newTypeWithName(const char *name,
- const char *cppName,
- PyTypeObject *numbers_fromFlag)
+template <typename IntT>
+static PyObject *toPyObject(IntT v)
{
- if (!useOldEnum)
- PyErr_Format(PyExc_RuntimeError, "function `%s` can no longer be used when the Python "
- "Enum's have been selected", __FUNCTION__);
- return newTypeWithNameOld(name, cppName, numbers_fromFlag);
+ if constexpr (sizeof(IntT) == 8) {
+ if constexpr (std::is_unsigned_v<IntT>)
+ return PyLong_FromUnsignedLongLong(v);
+ return PyLong_FromLongLong(v);
+ }
+ if constexpr (std::is_unsigned_v<IntT>)
+ return PyLong_FromUnsignedLong(v);
+ return PyLong_FromLong(v);
}
-const char *getCppName(PyTypeObject *enumType)
+template <typename IntT>
+static PyTypeObject *createPythonEnumHelper(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const IntT enumValues[])
{
- assert(Py_TYPE(enumType) == SbkEnumType_TypeF());
- auto *type = reinterpret_cast<SbkEnumType *>(enumType);
- auto *setp = PepType_SETP(type);
- return setp->cppName;
+ AutoDecRef args(PyList_New(0));
+ auto *pyEnumItems = args.object();
+ for (size_t idx = 0; enumItemStrings[idx] != nullptr; ++idx) {
+ const char *kv = enumItemStrings[idx];
+ auto *key = PyUnicode_FromString(kv);
+ auto *value = toPyObject(enumValues[idx]);
+ auto *key_value = PyTuple_New(2);
+ PyTuple_SET_ITEM(key_value, 0, key);
+ PyTuple_SET_ITEM(key_value, 1, value);
+ PyList_Append(pyEnumItems, key_value);
+ }
+ return createEnumForPython(module, fullName, pyEnumItems);
}
-long int getValue(PyObject *enumItem)
-{
- init_enum();
-
- assert(Enum::check(enumItem));
-
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return reinterpret_cast<SbkEnumObject *>(enumItem)->ob_value;
-
- AutoDecRef pyValue(PyObject_GetAttrString(enumItem, "value"));
- return PyLong_AsLong(pyValue);
-}
+// Now we have to concretize these functions explicitly,
+// otherwise templates will not work across modules.
-void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag)
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int64_t enumValues[])
{
- if (isFlag) {
- auto *flagsType = reinterpret_cast<PySideQFlagsType *>(type);
- PepType_PFTP(flagsType)->converter = converter;
- }
- else {
- auto *enumType = reinterpret_cast<SbkEnumType *>(type);
- PepType_SETP(enumType)->converter = converter;
- }
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-} // namespace Enum
-
-DeclaredEnumTypes &DeclaredEnumTypes::instance()
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint64_t enumValues[])
{
- static DeclaredEnumTypes me;
- return me;
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-DeclaredEnumTypes::DeclaredEnumTypes() = default;
-
-DeclaredEnumTypes::~DeclaredEnumTypes()
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int32_t enumValues[])
{
- cleanup();
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-void DeclaredEnumTypes::cleanup()
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint32_t enumValues[])
{
- static bool was_called = false;
- if (was_called)
- return;
-
- for (const auto &e : m_enumTypes) {
- std::free(e.name);
- }
- m_enumTypes.clear();
- was_called = true;
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-} // namespace Shiboken
-
-static void cleanupEnumTypes()
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int16_t enumValues[])
{
- DeclaredEnumTypes::instance().cleanup();
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-///////////////////////////////////////////////////////////////////////
-//
-// PYSIDE-1735: Re-implementation of Enums using Python
-// ====================================================
-//
-// This is a very simple, first implementation of a replacement
-// for the Qt-like Enums using the Python Enum module.
-//
-// The basic idea:
-// ---------------
-// * We create the Enums as always
-// * After creation of each enum, a special function is called that
-// * grabs the last generated enum
-// * reads all Enum items
-// * generates a class statement for the Python Enum
-// * creates a new Python Enum class
-// * replaces the already inserted Enum with the new one.
-//
-// There are lots of ways to optimize that. Will be added later.
-//
-extern "C" {
-
-struct lastEnumCreated {
- PyObject *scopeOrModule;
- const char *name;
- PyTypeObject *enumType;
- PyTypeObject *flagsType;
-};
-
-static lastEnumCreated lec{};
-
-static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
- const char *name,
- PyTypeObject *enumType,
- PyTypeObject *flagsType)
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint16_t enumValues[])
{
- lec.scopeOrModule = scopeOrModule;
- lec.name = name;
- lec.enumType = enumType;
- lec.flagsType = flagsType;
-
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return flagsType;
-
- // We return nullptr as flagsType to disable flag creation.
- return nullptr;
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-PyTypeObject *morphLastEnumToPython()
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int8_t enumValues[])
{
- /// The Python Enum internal structure is way too complicated.
- /// It is much easier to generate Python code and execute it.
-
- // Pick up the last generated Enum and convert it into a PyEnum
- auto *enumType = lec.enumType;
- // This is temporary; SbkEnumType will be removed, soon.
-
- // PYSIDE-1735: Decide dynamically if new or old enums will be used.
- if (useOldEnum)
- return enumType;
-
- auto *setp = PepType_SETP(reinterpret_cast<SbkEnumType *>(enumType));
- if (setp->replacementType) {
- // For some (yet to fix) reason, initialization of the enums can happen twice.
- // If that happens, use the existing new type to keep type checks correct.
- return setp->replacementType;
- }
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- PyObject *values = PyDict_GetItem(enumType->tp_dict, PyName::values());
- if (!values)
- return nullptr;
-
- // Walk the values dict and create a Python enum type.
- auto *PyEnumType = lec.flagsType ? PyIntFlag : PyIntEnum;
- AutoDecRef name(PyUnicode_FromString(lec.name));
- AutoDecRef args(PyList_New(0));
- auto *pyName = name.object();
- auto *pyArgs = args.object();
- while (PyDict_Next(values, &pos, &key, &value)) {
- auto *key_value = PyTuple_New(2);
- PyTuple_SET_ITEM(key_value, 0, key);
- Py_INCREF(key);
- auto *obj = reinterpret_cast<SbkEnumObject *>(value);
- auto *num = PyLong_FromLong(obj->ob_value);
- PyTuple_SET_ITEM(key_value, 1, num);
- PyList_Append(pyArgs, key_value);
- }
- auto *obNewType = PyObject_CallFunctionObjArgs(PyEnumType, pyName, pyArgs, nullptr);
- if (!obNewType || PyObject_SetAttr(lec.scopeOrModule, pyName, obNewType) < 0)
- return nullptr;
- auto *newType = reinterpret_cast<PyTypeObject *>(obNewType);
- auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
- AutoDecRef qual_name(PyObject_GetAttr(obEnumType, PyMagicName::qualname()));
- PyObject_SetAttr(obNewType, PyMagicName::qualname(), qual_name);
- AutoDecRef module(PyObject_GetAttr(obEnumType, PyMagicName::module()));
- PyObject_SetAttr(obNewType, PyMagicName::module(), module);
- // Protect against double initialization
- setp->replacementType = newType;
-#if PY_VERSION_HEX < 0x03080000
- // PYSIDE-1735: Old Python versions can't stand the early enum deallocation.
- Py_INCREF(enumType);
-#endif
- return newType;
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObject *EType)
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint8_t enumValues[])
{
- // this will be switchable...
- return useOldEnum ? FType : EType;
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
}
-} // extern "C"
+} // namespace Shiboken::Enum
diff --git a/sources/shiboken6/libshiboken/sbkenum.h b/sources/shiboken6/libshiboken/sbkenum.h
index 8b266710e..e19ca4b4c 100644
--- a/sources/shiboken6/libshiboken/sbkenum.h
+++ b/sources/shiboken6/libshiboken/sbkenum.h
@@ -10,77 +10,93 @@
extern "C"
{
+LIBSHIBOKEN_API bool PyEnumMeta_Check(PyObject *ob);
+
/// exposed for the signature module
LIBSHIBOKEN_API void init_enum();
-extern LIBSHIBOKEN_API PyTypeObject *SbkEnumType_TypeF(void);
struct SbkConverter;
struct SbkEnumType;
-struct SbkEnumTypePrivate;
-
-} // extern "C"
-namespace Shiboken
+struct SbkEnumTypePrivate
{
+ SbkConverter *converter;
+};
+
+/// PYSIDE-1735: Pass on the Python enum/flag information.
+LIBSHIBOKEN_API void initEnumFlagsDict(PyTypeObject *type);
+
+/// PYSIDE-1735: Make sure that we can import the Python enum implementation.
+LIBSHIBOKEN_API PyTypeObject *getPyEnumMeta();
+/// PYSIDE-1735: Helper function supporting QEnum
+LIBSHIBOKEN_API int enumIsFlag(PyObject *ob_enum);
-inline bool isShibokenEnum(PyObject *pyObj)
-{
- return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF();
}
-namespace Enum
+namespace Shiboken::Enum {
+
+enum : int {
+ ENOPT_OLD_ENUM = 0x00, // PySide 6.6: no longer supported
+ ENOPT_NEW_ENUM = 0x01,
+ ENOPT_INHERIT_INT = 0x02,
+ ENOPT_GLOBAL_SHORTCUT = 0x04,
+ ENOPT_SCOPED_SHORTCUT = 0x08,
+ ENOPT_NO_FAKESHORTCUT = 0x10,
+ ENOPT_NO_FAKERENAMES = 0x20,
+ ENOPT_NO_ZERODEFAULT = 0x40,
+ ENOPT_NO_MISSING = 0x80,
+};
+
+LIBSHIBOKEN_API extern int enumOption;
+
+using EnumValueType = long long;
+
+LIBSHIBOKEN_API bool check(PyObject *obj);
+
+LIBSHIBOKEN_API PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
+ const char *itemName = nullptr);
+
+LIBSHIBOKEN_API EnumValueType getValue(PyObject *enumItem);
+LIBSHIBOKEN_API PyObject *getEnumItemFromValue(PyTypeObject *enumType,
+ EnumValueType itemValue);
+
+/// Sets the enum/flag's type converter.
+LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *type, SbkConverter *converter);
+
+/// Creating Python enums for different types.
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int64_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint64_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int32_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint32_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int16_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint16_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const int8_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], const uint8_t enumValues[]);
+
+/// This template removes duplication by inlining necessary type casts.
+template <typename IntT>
+inline PyTypeObject *createPythonEnum(PyTypeObject *scope,
+ const char *fullName, const char *enumItemStrings[], const IntT enumValues[])
{
- LIBSHIBOKEN_API bool check(PyObject *obj);
- /**
- * Creates a new enum type (and its flags type, if any is given)
- * and registers it to Python and adds it to \p module.
- * \param module Module to where the new enum type will be added.
- * \param name Name of the enum.
- * \param fullName Name of the enum that includes all scope information (e.g.: "module.Enum").
- * \param cppName Full qualified C++ name of the enum.
- * \param flagsType Optional Python type for the flags associated with the enum.
- * \return The new enum type or NULL if it fails.
- */
- LIBSHIBOKEN_API PyTypeObject *createGlobalEnum(PyObject *module,
- const char *name,
- const char *fullName,
- const char *cppName,
- PyTypeObject *flagsType = nullptr);
- /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace.
- LIBSHIBOKEN_API PyTypeObject *createScopedEnum(PyTypeObject *scope,
- const char *name,
- const char *fullName,
- const char *cppName,
- PyTypeObject *flagsType = nullptr);
-
- /**
- * Creates a new enum item for a given enum type and adds it to \p module.
- * \param enumType Enum type to where the new enum item will be added.
- * \param module Module to where the enum type of the new enum item belongs.
- * \param itemName Name of the enum item.
- * \param itemValue Numerical value of the enum item.
- * \return true if everything goes fine, false if it fails.
- */
- LIBSHIBOKEN_API bool createGlobalEnumItem(PyTypeObject *enumType, PyObject *module, const char *itemName, long itemValue);
- /// This function does the same as createGlobalEnumItem, but adds the enum to a Shiboken type or namespace.
- LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
- const char *itemName, long itemValue);
-
- LIBSHIBOKEN_API PyObject *newItem(PyTypeObject *enumType, long itemValue, const char *itemName = nullptr);
-
- LIBSHIBOKEN_API PyTypeObject *newTypeWithName(const char *name, const char *cppName,
- PyTypeObject *numbers_fromFlag=nullptr);
- LIBSHIBOKEN_API const char *getCppName(PyTypeObject *type);
-
- LIBSHIBOKEN_API long getValue(PyObject *enumItem);
- LIBSHIBOKEN_API PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue);
-
- /// Sets the enum/flag's type converter.
- LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag);
-
- LIBSHIBOKEN_API PyObject *unpickleEnum(PyObject *, PyObject *);
+ auto *obScope = reinterpret_cast<PyObject *>(scope);
+ return createPythonEnum(obScope, fullName, enumItemStrings, enumValues);
}
-} // namespace Shiboken
+} // namespace Shiboken::Enum
#endif // SKB_PYENUM_H
diff --git a/sources/shiboken6/libshiboken/sbkenum_p.h b/sources/shiboken6/libshiboken/sbkenum_p.h
deleted file mode 100644
index 9e6fd6a61..000000000
--- a/sources/shiboken6/libshiboken/sbkenum_p.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef SBKENUM_P_H
-#define SBKENUM_P_H
-
-#include "sbkpython.h"
-#include "shibokenmacros.h"
-
-struct SbkEnumTypePrivate
-{
- SbkConverter *converter;
- const char *cppName;
- PyTypeObject *replacementType;
-};
-
-extern "C" {
-
-/// PYSIDE-1735: Patching the Enum / Flags implementation. Remove in 6.4
-LIBSHIBOKEN_API PyTypeObject *morphLastEnumToPython();
-LIBSHIBOKEN_API PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObject *EType);
-
-/// PYSIDE-1735: Make sure that we can import the Python enum implementation.
-LIBSHIBOKEN_API PyTypeObject *getPyEnumMeta();
-/// PYSIDE-1735: Helper function supporting QEnum
-LIBSHIBOKEN_API int enumIsFlag(PyObject *ob_enum);
-
-}
-
-#endif // SBKENUM_P_H
diff --git a/sources/shiboken6/libshiboken/sbkerrors.cpp b/sources/shiboken6/libshiboken/sbkerrors.cpp
index 38da36b16..1832624d5 100644
--- a/sources/shiboken6/libshiboken/sbkerrors.cpp
+++ b/sources/shiboken6/libshiboken/sbkerrors.cpp
@@ -2,10 +2,37 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "sbkerrors.h"
+#include "sbkstring.h"
#include "helper.h"
+#include "gilstate.h"
namespace Shiboken
{
+
+// PYSIDE-2335: Track down if we can reach a Python error handler.
+// _pythonContextStack has always the current state of handler status
+// in its lowest bit.
+// Blocking calls like exec or run need to use `setBlocking`.
+static thread_local std::size_t _pythonContextStack{};
+
+PythonContextMarker::PythonContextMarker()
+{
+ // Shift history up and set lowest bit.
+ _pythonContextStack = (_pythonContextStack * 2) + 1;
+}
+
+PythonContextMarker::~PythonContextMarker()
+{
+ // Shift history down.
+ _pythonContextStack /= 2;
+}
+
+void PythonContextMarker::setBlocking()
+{
+ // Clear lowest bit.
+ _pythonContextStack = _pythonContextStack / 2 * 2;
+}
+
namespace Errors
{
@@ -66,6 +93,34 @@ void setWrongContainerType()
PyErr_SetString(PyExc_TypeError, "Wrong type passed to container conversion.");
}
+struct ErrorStore {
+ PyObject *type;
+ PyObject *exc;
+ PyObject *traceback;
+};
+
+static thread_local ErrorStore savedError{};
+
+void storeErrorOrPrint()
+{
+ // This error happened in a function with no way to return an error state.
+ // Therefore, we handle the error when we are error checking, anyway.
+ // But we do that only when we know that an error handler can pick it up.
+ if (_pythonContextStack & 1)
+ PyErr_Fetch(&savedError.type, &savedError.exc, &savedError.traceback);
+ else
+ PyErr_Print();
+}
+
+PyObject *occurred()
+{
+ if (savedError.type) {
+ PyErr_Restore(savedError.type, savedError.exc, savedError.traceback);
+ savedError.type = nullptr;
+ }
+ return PyErr_Occurred();
+}
+
} // namespace Errors
namespace Warnings
@@ -94,5 +149,22 @@ void warnDeprecated(const char *className, const char *functionName)
className, functionName);
}
+void warnDeprecatedEnum(const char *enumName)
+{
+ Shiboken::warning(PyExc_DeprecationWarning, 1,
+ "Enum: '%s' is marked as deprecated, please check "
+ "the documentation for more information.",
+ enumName);
+}
+
+void warnDeprecatedEnumValue(const char *enumName, const char *valueName)
+{
+ Shiboken::warning(PyExc_DeprecationWarning, 1,
+ "Enum value '%s.%s' is marked as deprecated, please check "
+ "the documentation for more information.",
+ enumName, valueName);
+
+}
+
} // namespace Warnings
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/sbkerrors.h b/sources/shiboken6/libshiboken/sbkerrors.h
index cc86c10b9..6ff85f8e1 100644
--- a/sources/shiboken6/libshiboken/sbkerrors.h
+++ b/sources/shiboken6/libshiboken/sbkerrors.h
@@ -7,8 +7,31 @@
#include "sbkpython.h"
#include "shibokenmacros.h"
+/// Craving for C++20 and std::source_location::current()
+#if defined(_MSC_VER)
+# define SBK_FUNC_INFO __FUNCSIG__
+#elif defined(__GNUC__)
+# define SBK_FUNC_INFO __PRETTY_FUNCTION__
+#else
+# define SBK_FUNC_INFO __FUNCTION__
+#endif
+
namespace Shiboken
{
+
+struct LIBSHIBOKEN_API PythonContextMarker
+{
+public:
+ PythonContextMarker(const PythonContextMarker &) = delete;
+ PythonContextMarker(PythonContextMarker &&) = delete;
+ PythonContextMarker &operator=(const PythonContextMarker &) = delete;
+ PythonContextMarker &operator=(PythonContextMarker &&) = delete;
+
+ explicit PythonContextMarker();
+ ~PythonContextMarker();
+ void setBlocking();
+};
+
namespace Errors
{
@@ -23,6 +46,15 @@ LIBSHIBOKEN_API void setSequenceTypeError(const char *expectedType);
LIBSHIBOKEN_API void setSetterTypeError(const char *name, const char *expectedType);
LIBSHIBOKEN_API void setWrongContainerType();
+/// Report an error ASAP: Instead of printing, store for later re-raise.
+/// This replaces `PyErr_Print`, which cannot report errors as exception.
+/// To be used in contexts where raising errors is impossible.
+LIBSHIBOKEN_API void storeErrorOrPrint();
+/// Handle an error as in PyErr_Occurred(), but also check for errors which
+/// were captured by `storeErrorOrPrint`.
+/// To be used in normal error checks.
+LIBSHIBOKEN_API PyObject *occurred();
+
} // namespace Errors
namespace Warnings
@@ -32,6 +64,8 @@ LIBSHIBOKEN_API void warnInvalidReturnValue(const char *className, const char *f
const char *expectedType, const char *actualType);
LIBSHIBOKEN_API void warnDeprecated(const char *functionName);
LIBSHIBOKEN_API void warnDeprecated(const char *className, const char *functionName);
+LIBSHIBOKEN_API void warnDeprecatedEnum(const char *enumName);
+LIBSHIBOKEN_API void warnDeprecatedEnumValue(const char *enumName, const char *valueName);
} // namespace Warnings
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.cpp b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
index e191204e4..f31b8f4f7 100644
--- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp
+++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
@@ -4,12 +4,16 @@
#include "basewrapper.h"
#include "basewrapper_p.h"
#include "autodecref.h"
-#include "sbkenum_p.h"
+#include "pep384ext.h"
+#include "sbkenum.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
#include "signature.h"
#include "sbkfeature_base.h"
+#include "gilstate.h"
+
+#include <cctype>
using namespace Shiboken;
@@ -18,64 +22,293 @@ extern "C"
////////////////////////////////////////////////////////////////////////////
//
-// getFeatureSelectId
+// Minimal __feature__ support in Shiboken
//
-// This function is needed here already for signature handling.
-// Maybe the same function from feature_select.cpp will be replaced.
+int currentSelectId(PyTypeObject *type)
+{
+ AutoDecRef tpDict(PepType_GetDict(type));
+ PyObject *PyId = PyObject_GetAttr(tpDict.object(), PyName::select_id());
+ if (PyId == nullptr) {
+ PyErr_Clear();
+ return 0x00;
+ }
+ int sel = PyLong_AsLong(PyId);
+ Py_DECREF(PyId);
+ return sel;
+}
+
+static SelectableFeatureHook SelectFeatureSet = nullptr;
+static SelectableFeatureCallback featureCb = nullptr;
+
+void setSelectableFeatureCallback(SelectableFeatureCallback func)
+{
+ featureCb = func;
+}
+
+SelectableFeatureHook initSelectableFeature(SelectableFeatureHook func)
+{
+ auto ret = SelectFeatureSet;
+ SelectFeatureSet = func;
+ if (featureCb)
+ featureCb(SelectFeatureSet != nullptr);
+ return ret;
+}
//
+////////////////////////////////////////////////////////////////////////////
-static PyObject *cached_globals{};
-static PyObject *last_select_id{};
+// This useful function is for debugging
+void disassembleFrame(const char *marker)
+{
+ Shiboken::GilState gil;
+ PyObject *error_type, *error_value, *error_traceback;
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ static PyObject *dismodule = PyImport_ImportModule("dis");
+ static PyObject *disco = PyObject_GetAttrString(dismodule, "disco");
+ static PyObject *const _f_lasti = Shiboken::String::createStaticString("f_lasti");
+ static PyObject *const _f_lineno = Shiboken::String::createStaticString("f_lineno");
+ static PyObject *const _f_code = Shiboken::String::createStaticString("f_code");
+ static PyObject *const _co_filename = Shiboken::String::createStaticString("co_filename");
+ AutoDecRef ignore{};
+ auto *frame = reinterpret_cast<PyObject *>(PyEval_GetFrame());
+ if (frame == nullptr) {
+ fprintf(stdout, "\n%s BEGIN no frame END\n\n", marker);
+ } else {
+ AutoDecRef f_lasti(PyObject_GetAttr(frame, _f_lasti));
+ AutoDecRef f_lineno(PyObject_GetAttr(frame, _f_lineno));
+ AutoDecRef f_code(PyObject_GetAttr(frame, _f_code));
+ AutoDecRef co_filename(PyObject_GetAttr(f_code, _co_filename));
+ long line = PyLong_AsLong(f_lineno);
+ const char *fname = String::toCString(co_filename);
+ fprintf(stdout, "\n%s BEGIN line=%ld %s\n", marker, line, fname);
+ ignore.reset(PyObject_CallFunctionObjArgs(disco, f_code.object(), f_lasti.object(), nullptr));
+ fprintf(stdout, "%s END line=%ld %s\n\n", marker, line, fname);
+ }
+#if PY_VERSION_HEX >= 0x030C0000 && !Py_LIMITED_API
+ if (error_type)
+ PyErr_DisplayException(error_value);
+#endif
+ static PyObject *stdout_file = PySys_GetObject("stdout");
+ ignore.reset(PyObject_CallMethod(stdout_file, "flush", nullptr));
+ PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+// python 3.12
+static int const CALL = 171;
+// Python 3.11
+static int const PRECALL = 166;
+// we have "big instructions" with gaps after them
+static int const LOAD_METHOD_GAP_311 = 10 * 2;
+static int const LOAD_ATTR_GAP_311 = 4 * 2;
+static int const LOAD_ATTR_GAP = 9 * 2;
+// Python 3.7 - 3.10
+static int const LOAD_METHOD = 160;
+static int const CALL_METHOD = 161;
+// Python 3.6
+static int const CALL_FUNCTION = 131;
+static int const LOAD_ATTR = 106;
+// NoGil (how long will this exist in this form?)
+static int const LOAD_METHOD_NOGIL = 55;
+static int const CALL_METHOD_NOGIL = 72;
-PyObject *getFeatureSelectId()
+static bool currentOpcode_Is_CallMethNoArgs()
{
- static PyObject *undef = PyLong_FromLong(-1);
- static PyObject *feature_dict = GetFeatureDict();
- // these things are all borrowed
- PyObject *globals = PyEval_GetGlobals();
- if (globals == nullptr
- || globals == cached_globals)
- return last_select_id;
+ // PYSIDE-2221: Special case for the NoGil version:
+ // Find out if we have such a version.
+ // We could also ask the variable `Py_NOGIL`.
+ static PyObject *flags = PySys_GetObject("flags");
+ static bool isNoGil = PyObject_HasAttrString(flags, "nogil");
+ // We look into the currently active operation if we are going to call
+ // a method with zero arguments.
+ auto *frame = PyEval_GetFrame();
+#if !Py_LIMITED_API && !defined(PYPY_VERSION)
+ auto *f_code = PyFrame_GetCode(frame);
+#else
+ static PyObject *const _f_code = Shiboken::String::createStaticString("f_code");
+ AutoDecRef dec_f_code(PyObject_GetAttr(reinterpret_cast<PyObject *>(frame), _f_code));
+ auto *f_code = dec_f_code.object();
+#endif
+#if PY_VERSION_HEX >= 0x030B0000 && !Py_LIMITED_API
+ AutoDecRef dec_co_code(PyCode_GetCode(f_code));
+ Py_ssize_t f_lasti = PyFrame_GetLasti(frame);
+#else
+ static PyObject *const _f_lasti = Shiboken::String::createStaticString("f_lasti");
+ static PyObject *const _co_code = Shiboken::String::createStaticString("co_code");
+ AutoDecRef dec_co_code(PyObject_GetAttr(reinterpret_cast<PyObject *>(f_code), _co_code));
+ AutoDecRef dec_f_lasti(PyObject_GetAttr(reinterpret_cast<PyObject *>(frame), _f_lasti));
+ Py_ssize_t f_lasti = PyLong_AsSsize_t(dec_f_lasti);
+#endif
+ Py_ssize_t code_len;
+ char *co_code{};
+ PyBytes_AsStringAndSize(dec_co_code, &co_code, &code_len);
+ uint8_t opcode1 = co_code[f_lasti];
+ if (isNoGil) {
+ uint8_t opcode2 = co_code[f_lasti + 4];
+ uint8_t oparg2 = co_code[f_lasti + 6];
+ return opcode1 == LOAD_METHOD_NOGIL && opcode2 == CALL_METHOD_NOGIL && oparg2 == 1;
+ }
+ uint8_t opcode2 = co_code[f_lasti + 2];
+ uint8_t oparg2 = co_code[f_lasti + 3];
+ static auto number = _PepRuntimeVersion();
+ if (number < 0x030B00)
+ return opcode1 == LOAD_METHOD && opcode2 == CALL_METHOD && oparg2 == 0;
+
+ if (number < 0x030C00) {
+ // With Python 3.11, the opcodes get bigger and change a bit.
+ // Note: The new adaptive opcodes are elegantly hidden and we
+ // don't need to take care of them.
+ if (opcode1 == LOAD_METHOD)
+ f_lasti += LOAD_METHOD_GAP_311;
+ else if (opcode1 == LOAD_ATTR)
+ f_lasti += LOAD_ATTR_GAP_311;
+ else
+ return false;
+
+ opcode2 = co_code[f_lasti + 2];
+ oparg2 = co_code[f_lasti + 3];
- PyObject *modname = PyDict_GetItem(globals, PyMagicName::name());
- if (modname == nullptr)
- return last_select_id;
+ return opcode2 == PRECALL && oparg2 == 0;
+ }
+ // With Python 3.12, the opcodes get again bigger and change a bit.
+ // Note: The new adaptive opcodes are elegantly hidden and we
+ // don't need to take care of them.
+ if (opcode1 == LOAD_ATTR)
+ f_lasti += LOAD_ATTR_GAP;
+ else
+ return false;
- PyObject *select_id = PyDict_GetItem(feature_dict, modname);
- if (select_id == nullptr
- || !PyLong_Check(select_id) // int/long cheating
- || select_id == undef)
- return last_select_id;
+ opcode2 = co_code[f_lasti + 2];
+ oparg2 = co_code[f_lasti + 3];
- cached_globals = globals;
- last_select_id = select_id;
- assert(PyLong_AsSsize_t(select_id) >= 0);
- return select_id;
+ return opcode2 == CALL && oparg2 == 0;
}
-int currentSelectId(PyTypeObject *type)
+void initEnumFlagsDict(PyTypeObject *type)
{
- int sel = SbkObjectType_GetReserved(type);
- // This could theoretically be -1 if used too early.
- assert(sel >= 0);
- return sel;
+ // We create a dict for all flag enums that holds the original C++ name
+ // and a dict that gives every enum/flag type name.
+ static PyObject *const split = Shiboken::String::createStaticString("split");
+ static PyObject *const colon = Shiboken::String::createStaticString(":");
+ auto sotp = PepType_SOTP(type);
+ auto **enumFlagInfo = sotp->enumFlagInfo;
+ auto *dict = PyDict_New();
+ auto *typeDict = PyDict_New();
+ for (; *enumFlagInfo; ++enumFlagInfo) {
+ AutoDecRef line(PyUnicode_FromString(*enumFlagInfo));
+ AutoDecRef parts(PyObject_CallMethodObjArgs(line, split, colon, nullptr));
+ auto *name = PyList_GetItem(parts, 0);
+ if (PyList_Size(parts) == 3) {
+ auto *key = PyList_GetItem(parts, 2);
+ auto *value = name;
+ PyDict_SetItem(dict, key, value);
+ }
+ auto *typeName = PyList_GetItem(parts, 1);
+ PyDict_SetItem(typeDict, name, typeName);
+ }
+ sotp->enumFlagsDict = dict;
+ sotp->enumTypeDict = typeDict;
}
-void initFeatureShibokenPart()
+static PyObject *replaceNoArgWithZero(PyObject *callable)
{
- static PyObject *no_sel = PyLong_FromLong(0);
- last_select_id = no_sel;
- // Reset the cache. This is called at any "from __feature__ import".
- cached_globals = nullptr;
+ static auto *partial = Pep_GetPartialFunction();
+ static auto *zero = PyLong_FromLong(0);
+ return PyObject_CallFunctionObjArgs(partial, callable, zero, nullptr);
}
-static SelectableFeatureHook SelectFeatureSet = nullptr;
-
-SelectableFeatureHook initSelectableFeature(SelectableFeatureHook func)
+static PyObject *lookupUnqualifiedOrOldEnum(PyTypeObject *type, PyObject *name)
{
- auto ret = SelectFeatureSet;
- SelectFeatureSet = func;
- return ret;
+ // MRO has been observed to be 0 in case of errors with QML decorators
+ if (type == nullptr || type->tp_mro == nullptr)
+ return nullptr;
+ // Quick Check: Avoid "__..", "_slots", etc.
+ if (std::isalpha(Shiboken::String::toCString(name)[0]) == 0)
+ return nullptr;
+ static PyTypeObject *const EnumMeta = getPyEnumMeta();
+ static PyObject *const _member_map_ = String::createStaticString("_member_map_");
+ // This is similar to `find_name_in_mro`, but instead of looking directly into
+ // tp_dict, we also search for the attribute in local classes of that dict (Part 2).
+ PyObject *mro = type->tp_mro;
+ PyObject *result{};
+ assert(PyTuple_Check(mro));
+ Py_ssize_t idx, n = PyTuple_GET_SIZE(mro);
+ for (idx = 0; idx < n; ++idx) {
+ auto *base = PyTuple_GET_ITEM(mro, idx);
+ auto *type_base = reinterpret_cast<PyTypeObject *>(base);
+ if (!SbkObjectType_Check(type_base))
+ continue;
+ auto sotp = PepType_SOTP(type_base);
+ // The EnumFlagInfo structure tells us if there are Enums at all.
+ const char **enumFlagInfo = sotp->enumFlagInfo;
+ if (!(enumFlagInfo))
+ continue;
+ if (!sotp->enumFlagsDict)
+ initEnumFlagsDict(type_base);
+ bool useFakeRenames = !(Enum::enumOption & Enum::ENOPT_NO_FAKERENAMES);
+ if (useFakeRenames) {
+ auto *rename = PyDict_GetItem(sotp->enumFlagsDict, name);
+ if (rename) {
+ /*
+ * Part 1: Look into the enumFlagsDict if we have an old flags name.
+ * -------------------------------------------------------------
+ * We need to replace the parameterless
+
+ QtCore.Qt.Alignment()
+
+ * by the one-parameter call
+
+ QtCore.Qt.AlignmentFlag(0)
+
+ * That means: We need to bind the zero as default into a wrapper and
+ * return that to be called.
+ *
+ * Addendum:
+ * ---------
+ * We first need to look into the current opcode of the bytecode to find
+ * out if we have a call like above or just a type lookup.
+ */
+ AutoDecRef tpDict(PepType_GetDict(type_base));
+ auto *flagType = PyDict_GetItem(tpDict.object(), rename);
+ if (currentOpcode_Is_CallMethNoArgs())
+ return replaceNoArgWithZero(flagType);
+ Py_INCREF(flagType);
+ return flagType;
+ }
+ }
+ bool useFakeShortcuts = !(Enum::enumOption & Enum::ENOPT_NO_FAKESHORTCUT);
+ if (useFakeShortcuts) {
+ AutoDecRef tpDict(PepType_GetDict(type_base));
+ auto *dict = tpDict.object();
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ /*
+ * Part 2: Check for a duplication into outer scope.
+ * -------------------------------------------------
+ * We need to replace the shortcut
+
+ QtCore.Qt.AlignLeft
+
+ * by the correct call
+
+ QtCore.Qt.AlignmentFlag.AlignLeft
+
+ * That means: We need to search all Enums of the class.
+ */
+ if (Py_TYPE(value) == EnumMeta) {
+ auto *valtype = reinterpret_cast<PyTypeObject *>(value);
+ AutoDecRef valtypeDict(PepType_GetDict(valtype));
+ auto *member_map = PyDict_GetItem(valtypeDict.object(), _member_map_);
+ if (member_map && PyDict_Check(member_map)) {
+ result = PyDict_GetItem(member_map, name);
+ Py_XINCREF(result);
+ if (result)
+ return result;
+ }
+ }
+ }
+ }
+ }
+ return nullptr;
}
PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
@@ -86,67 +319,64 @@ PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
* with the complex `tp_getattro` of `QObject` and other instances.
* What we change here is the meta class of `QObject`.
*/
- static getattrofunc type_getattro = PyType_Type.tp_getattro;
- static PyObject *ignAttr1 = PyName::qtStaticMetaObject();
- static PyObject *ignAttr2 = PyMagicName::get();
+ static getattrofunc const type_getattro = PepExt_Type_GetGetAttroSlot(&PyType_Type);
+ static PyObject *const ignAttr1 = PyName::qtStaticMetaObject();
+ static PyObject *const ignAttr2 = PyMagicName::get();
+ static PyTypeObject *const EnumMeta = getPyEnumMeta();
+
if (SelectFeatureSet != nullptr)
- type->tp_dict = SelectFeatureSet(type);
+ SelectFeatureSet(type);
auto *ret = type_getattro(reinterpret_cast<PyObject *>(type), name);
// PYSIDE-1735: Be forgiving with strict enums and fetch the enum, silently.
// The PYI files now look correct, but the old duplication is
// emulated here. This should be removed in Qt 7, see `parser.py`.
//
- // FIXME PYSIDE7 should remove this forgivingness:
+ // FIXME PYSIDE7 should remove this forgiveness:
//
// The duplication of enum values into the enclosing scope, allowing to write
// Qt.AlignLeft instead of Qt.Alignment.AlignLeft, is still implemented but
// no longer advertized in PYI files or line completion.
+ if (ret && Py_TYPE(ret) == EnumMeta && currentOpcode_Is_CallMethNoArgs()) {
+ bool useZeroDefault = !(Enum::enumOption & Enum::ENOPT_NO_ZERODEFAULT);
+ if (useZeroDefault) {
+ // We provide a zero argument for compatibility if it is a call with no args.
+ auto *hold = replaceNoArgWithZero(ret);
+ Py_DECREF(ret);
+ ret = hold;
+ }
+ }
+
if (!ret && name != ignAttr1 && name != ignAttr2) {
- PyObject *error_type, *error_value, *error_traceback;
+ PyObject *error_type{}, *error_value{}, *error_traceback{};
PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- // This is similar to `find_name_in_mro`, but instead of looking directly into
- // tp_dict, we search for the attribute in local classes of that dict.
- PyObject *mro = type->tp_mro;
- assert(PyTuple_Check(mro));
- size_t idx, n = PyTuple_GET_SIZE(mro);
- for (idx = 0; idx < n; ++idx) {
- // FIXME This loop should further be optimized by installing an extra
- // <classname>_EnumInfo structure. This comes with the next compatibility patch.
- auto *base = PyTuple_GET_ITEM(mro, idx);
- auto *type_base = reinterpret_cast<PyTypeObject *>(base);
- auto *dict = type_base->tp_dict;
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(dict, &pos, &key, &value)) {
- static auto *EnumMeta = getPyEnumMeta();
- if (Py_TYPE(value) == EnumMeta) {
- auto *valtype = reinterpret_cast<PyTypeObject *>(value);
- auto *result = PyDict_GetItem(valtype->tp_dict, name);
- if (result) {
- Py_INCREF(result);
- return result;
- }
- }
- }
+ ret = lookupUnqualifiedOrOldEnum(type, name);
+ if (ret) {
+ Py_DECREF(error_type);
+ Py_XDECREF(error_value);
+ Py_XDECREF(error_traceback);
+ } else {
+ PyErr_Restore(error_type, error_value, error_traceback);
}
- PyErr_Restore(error_type, error_value, error_traceback);
}
return ret;
}
-PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context)
+PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void * /* context */)
{
/*
* This is the override for getting a dict.
*/
- auto dict = type->tp_dict;
+ AutoDecRef tpDict(PepType_GetDict(type));
+ auto *dict = tpDict.object();;
if (dict == nullptr)
Py_RETURN_NONE;
- if (SelectFeatureSet != nullptr)
- dict = SelectFeatureSet(type);
+ if (SelectFeatureSet != nullptr) {
+ SelectFeatureSet(type);
+ tpDict.reset(PepType_GetDict(type));
+ dict = tpDict.object();
+ }
return PyDictProxy_New(dict);
}
@@ -157,7 +387,7 @@ PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name)
{
auto type = Py_TYPE(obj);
if (SelectFeatureSet != nullptr)
- type->tp_dict = SelectFeatureSet(type);
+ SelectFeatureSet(type);
return PyObject_GenericGetAttr(obj, name);
}
@@ -165,21 +395,10 @@ int SbkObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
{
auto type = Py_TYPE(obj);
if (SelectFeatureSet != nullptr)
- type->tp_dict = SelectFeatureSet(type);
+ SelectFeatureSet(type);
return PyObject_GenericSetAttr(obj, name, value);
}
-// Caching the select Id.
-int SbkObjectType_GetReserved(PyTypeObject *type)
-{
- return PepType_SOTP(type)->pyside_reserved_bits;
-}
-
-void SbkObjectType_SetReserved(PyTypeObject *type, int value)
-{
- PepType_SOTP(type)->pyside_reserved_bits = value;
-}
-
const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type)
{
return PepType_SOTP(type)->propertyStrings;
@@ -190,11 +409,16 @@ void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings)
PepType_SOTP(type)->propertyStrings = strings;
}
+void SbkObjectType_SetEnumFlagInfo(PyTypeObject *type, const char **strings)
+{
+ PepType_SOTP(type)->enumFlagInfo = strings;
+}
+
// PYSIDE-1626: Enforcing a context switch without further action.
void SbkObjectType_UpdateFeature(PyTypeObject *type)
{
if (SelectFeatureSet != nullptr)
- type->tp_dict = SelectFeatureSet(type);
+ SelectFeatureSet(type);
}
} // extern "C"
diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.h b/sources/shiboken6/libshiboken/sbkfeature_base.h
index 8d55297d7..290884062 100644
--- a/sources/shiboken6/libshiboken/sbkfeature_base.h
+++ b/sources/shiboken6/libshiboken/sbkfeature_base.h
@@ -7,9 +7,7 @@
extern "C"
{
-LIBSHIBOKEN_API PyObject *getFeatureSelectId();
LIBSHIBOKEN_API int currentSelectId(PyTypeObject *type);
-LIBSHIBOKEN_API void initFeatureShibokenPart();
LIBSHIBOKEN_API PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name);
LIBSHIBOKEN_API PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context);
LIBSHIBOKEN_API PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name);
diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp
index 51ab4311b..5df34ef26 100644
--- a/sources/shiboken6/libshiboken/sbkmodule.cpp
+++ b/sources/shiboken6/libshiboken/sbkmodule.cpp
@@ -2,54 +2,496 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "sbkmodule.h"
+#include "autodecref.h"
#include "basewrapper.h"
#include "bindingmanager.h"
+#include "sbkstring.h"
+#include "sbkcppstring.h"
+
#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+#include <cstring>
+
+/// This hash maps module objects to arrays of converters.
+using ModuleConvertersMap = std::unordered_map<PyObject *, SbkConverter **> ;
/// This hash maps module objects to arrays of Python types.
-using ModuleTypesMap = std::unordered_map<PyObject *, PyTypeObject **> ;
+using ModuleTypesMap = std::unordered_map<PyObject *, Shiboken::Module::TypeInitStruct *> ;
-/// This hash maps module objects to arrays of converters.
-using ModuleConvertersMap = std::unordered_map<PyObject *, SbkConverter **>;
+struct TypeCreationStruct
+{
+ Shiboken::Module::TypeCreationFunction func;
+ std::vector<std::string> subtypeNames;
+};
+
+/// This hash maps type names to type creation structs.
+using NameToTypeFunctionMap = std::unordered_map<std::string, TypeCreationStruct> ;
+
+/// This hash maps module objects to maps of names to functions.
+using ModuleToFuncsMap = std::unordered_map<PyObject *, NameToTypeFunctionMap> ;
/// All types produced in imported modules are mapped here.
static ModuleTypesMap moduleTypes;
static ModuleConvertersMap moduleConverters;
+static ModuleToFuncsMap moduleToFuncs;
namespace Shiboken
{
namespace Module
{
+// PYSIDE-2404: Replacing the arguments generated by cpythonTypeNameExt
+// by a function call.
+LIBSHIBOKEN_API PyTypeObject *get(TypeInitStruct &typeStruct)
+{
+ if (typeStruct.type != nullptr)
+ return typeStruct.type;
+
+ static PyObject *sysModules = PyImport_GetModuleDict();
+
+ // The slow path for initialization.
+ // We get the type by following the chain from the module.
+ // As soon as types[index] gets filled, we can stop.
+
+ std::string_view names(typeStruct.fullName);
+ const bool usePySide = names.compare(0, 8, "PySide6.") == 0;
+ auto dotPos = usePySide ? names.find('.', 8) : names.find('.');
+ auto startPos = dotPos + 1;
+ AutoDecRef modName(String::fromCppStringView(names.substr(0, dotPos)));
+ auto *modOrType = PyDict_GetItem(sysModules, modName);
+ if (modOrType == nullptr) {
+ PyErr_Format(PyExc_SystemError, "Module %s should already be in sys.modules",
+ PyModule_GetName(modOrType));
+ return nullptr;
+ }
+
+ do {
+ dotPos = names.find('.', startPos);
+ auto typeName = dotPos != std::string::npos
+ ? names.substr(startPos, dotPos - startPos)
+ : names.substr(startPos);
+ startPos = dotPos + 1;
+ AutoDecRef obTypeName(String::fromCppStringView(typeName));
+ modOrType = PyObject_GetAttr(modOrType, obTypeName);
+ } while (typeStruct.type == nullptr && dotPos != std::string::npos);
+
+ return typeStruct.type;
+}
+
+static void incarnateHelper(PyObject *module, const std::string_view names,
+ const NameToTypeFunctionMap &nameToFunc)
+{
+ auto dotPos = names.find('.');
+ std::string::size_type startPos = 0;
+ auto *modOrType{module};
+ while (dotPos != std::string::npos) {
+ auto typeName = names.substr(startPos, dotPos - startPos);
+ AutoDecRef obTypeName(String::fromCppStringView(typeName));
+ modOrType = PyObject_GetAttr(modOrType, obTypeName);
+ startPos = dotPos + 1;
+ dotPos = names.find('.', startPos);
+ }
+ // now we have the type to create.
+ auto funcIter = nameToFunc.find(std::string(names));
+ // - call this function that returns a PyTypeObject
+ auto tcStruct = funcIter->second;
+ auto initFunc = tcStruct.func;
+ PyTypeObject *type = initFunc(modOrType);
+ auto name = names.substr(startPos);
+ PyObject_SetAttrString(modOrType, name.data(), reinterpret_cast<PyObject *>(type));
+}
+
+static void incarnateSubtypes(PyObject *module,
+ const std::vector<std::string> &nameList,
+ NameToTypeFunctionMap &nameToFunc)
+{
+ for (auto const & tableIter : nameList) {
+ std::string_view names(tableIter);
+ incarnateHelper(module, names, nameToFunc);
+ }
+}
+
+static PyTypeObject *incarnateType(PyObject *module, const char *name,
+ NameToTypeFunctionMap &nameToFunc)
+{
+ // - locate the name and retrieve the generating function
+ auto funcIter = nameToFunc.find(name);
+ if (funcIter == nameToFunc.end()) {
+ // attribute does really not exist.
+ PyErr_SetNone(PyExc_AttributeError);
+ return nullptr;
+ }
+ // - call this function that returns a PyTypeObject
+ auto tcStruct = funcIter->second;
+ auto initFunc = tcStruct.func;
+ auto *modOrType{module};
+
+ // PYSIDE-2404: Make sure that no switching happens during type creation.
+ auto saveFeature = initSelectableFeature(nullptr);
+ PyTypeObject *type = initFunc(modOrType);
+ if (!tcStruct.subtypeNames.empty())
+ incarnateSubtypes(module, tcStruct.subtypeNames, nameToFunc);
+ initSelectableFeature(saveFeature);
+
+ // - assign this object to the name in the module
+ auto *res = reinterpret_cast<PyObject *>(type);
+ Py_INCREF(res);
+ PyModule_AddObject(module, name, res); // steals reference
+ // - remove the entry, if not by something cleared.
+ if (!nameToFunc.empty())
+ nameToFunc.erase(funcIter);
+ // - return the PyTypeObject.
+ return type;
+}
+
+// PYSIDE-2404: Make sure that the mentioned classes really exist.
+// Used in `Pyside::typeName`. Because the result will be cached by
+// the creation of the type(s), this is efficient.
+void loadLazyClassesWithName(const char *name)
+{
+ for (auto const & tableIter : moduleToFuncs) {
+ auto nameToFunc = tableIter.second;
+ auto funcIter = nameToFunc.find(name);
+ if (funcIter != nameToFunc.end()) {
+ // attribute exists in the lazy types.
+ auto *module = tableIter.first;
+ incarnateType(module, name, nameToFunc);
+ }
+ }
+}
+
+// PYSIDE-2404: Completely load all not yet loaded classes.
+// This is needed to resolve a star import.
+void resolveLazyClasses(PyObject *module)
+{
+ // - locate the module in the moduleTofuncs mapping
+ auto tableIter = moduleToFuncs.find(module);
+ if (tableIter == moduleToFuncs.end())
+ return;
+
+ // - see if there are still unloaded elements
+ auto &nameToFunc = tableIter->second;
+
+ // - incarnate all types.
+ while (!nameToFunc.empty()) {
+ auto it = nameToFunc.begin();
+ auto attrNameStr = it->first;
+ incarnateType(module, attrNameStr.c_str(), nameToFunc);
+ }
+}
+
+// PYSIDE-2404: Override the gettattr function of modules.
+static getattrofunc origModuleGetattro{};
+
+// PYSIDE-2404: Use the patched module getattr to do on-demand initialization.
+// This modifies _all_ modules but should have no impact.
+static PyObject *PyModule_lazyGetAttro(PyObject *module, PyObject *name)
+{
+ // - check if the attribute is present and return it.
+ auto *attr = PyObject_GenericGetAttr(module, name);
+ // - we handle AttributeError, only.
+ if (!(attr == nullptr && PyErr_ExceptionMatches(PyExc_AttributeError)))
+ return attr;
+
+ PyErr_Clear();
+ // - locate the module in the moduleTofuncs mapping
+ auto tableIter = moduleToFuncs.find(module);
+ // - if this is not our module, use the original
+ if (tableIter == moduleToFuncs.end())
+ return origModuleGetattro(module, name);
+
+ // - locate the name and retrieve the generating function
+ const char *attrNameStr = Shiboken::String::toCString(name);
+ auto &nameToFunc = tableIter->second;
+ // - create the real type and handle subtypes
+ auto *type = incarnateType(module, attrNameStr, nameToFunc);
+ auto *ret = reinterpret_cast<PyObject *>(type);
+ // - if attribute does really not exist use the original
+ if (ret == nullptr && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ PyErr_Clear();
+ return origModuleGetattro(module, name);
+ }
+ return ret;
+}
+
+// PYSIDE-2404: Supply a new module dir for not yet visible entries.
+// This modification is only for "our" modules.
+static PyObject *_module_dir_template(PyObject * /* self */, PyObject *args)
+{
+ static PyObject *const _dict = Shiboken::String::createStaticString("__dict__");
+ // The dir function must replace all of the builtin function.
+ PyObject *module{};
+ if (!PyArg_ParseTuple(args, "O", &module))
+ return nullptr;
+
+ auto tableIter = moduleToFuncs.find(module);
+ assert(tableIter != moduleToFuncs.end());
+ Shiboken::AutoDecRef dict(PyObject_GetAttr(module, _dict));
+ auto *ret = PyDict_Keys(dict);
+ // Now add all elements that were not yet in the dict.
+ auto &nameToFunc = tableIter->second;
+ for (const auto &funcIter : nameToFunc) {
+ const char *name = funcIter.first.c_str();
+ Shiboken::AutoDecRef pyName(PyUnicode_FromString(name));
+ PyList_Append(ret, pyName);
+ }
+ return ret;
+}
+
+static PyMethodDef module_methods[] = {
+ {"__dir__", (PyCFunction)_module_dir_template, METH_VARARGS, nullptr},
+ {nullptr, nullptr, 0, nullptr}
+};
+
+// Python 3.8 - 3.12
+static int const LOAD_CONST_312 = 100;
+static int const IMPORT_NAME_312 = 108;
+
+static bool isImportStar(PyObject *module)
+{
+ // Find out whether we have a star import. This must work even
+ // when we have no import support from feature.
+ static PyObject *const _f_code = Shiboken::String::createStaticString("f_code");
+ static PyObject *const _f_lasti = Shiboken::String::createStaticString("f_lasti");
+ static PyObject *const _f_back = Shiboken::String::createStaticString("f_back");
+ static PyObject *const _co_code = Shiboken::String::createStaticString("co_code");
+ static PyObject *const _co_consts = Shiboken::String::createStaticString("co_consts");
+ static PyObject *const _co_names = Shiboken::String::createStaticString("co_names");
+
+ auto *obFrame = reinterpret_cast<PyObject *>(PyEval_GetFrame());
+ if (obFrame == nullptr)
+ return true; // better assume worst-case.
+
+ Py_INCREF(obFrame);
+ AutoDecRef dec_frame(obFrame);
+
+ // Calculate the offset of the running import_name opcode on the stack.
+ // Right before that there must be a load_const with the tuple `("*",)`.
+ while (dec_frame.object() != Py_None) {
+ AutoDecRef dec_f_code(PyObject_GetAttr(dec_frame, _f_code));
+ AutoDecRef dec_co_code(PyObject_GetAttr(dec_f_code, _co_code));
+ AutoDecRef dec_f_lasti(PyObject_GetAttr(dec_frame, _f_lasti));
+ Py_ssize_t f_lasti = PyLong_AsSsize_t(dec_f_lasti);
+ Py_ssize_t code_len;
+ char *co_code{};
+ PyBytes_AsStringAndSize(dec_co_code, &co_code, &code_len);
+ uint8_t opcode2 = co_code[f_lasti];
+ uint8_t opcode1 = co_code[f_lasti - 2];
+ if (opcode1 == LOAD_CONST_312 && opcode2 == IMPORT_NAME_312) {
+ uint8_t oparg1 = co_code[f_lasti - 1];
+ uint8_t oparg2 = co_code[f_lasti + 1];
+ AutoDecRef dec_co_consts(PyObject_GetAttr(dec_f_code, _co_consts));
+ auto *fromlist = PyTuple_GetItem(dec_co_consts, oparg1);
+ if (PyTuple_Check(fromlist) && PyTuple_Size(fromlist) == 1
+ && Shiboken::String::toCString(PyTuple_GetItem(fromlist, 0))[0] == '*') {
+ AutoDecRef dec_co_names(PyObject_GetAttr(dec_f_code, _co_names));
+ const char *name = String::toCString(PyTuple_GetItem(dec_co_names, oparg2));
+ const char *modName = PyModule_GetName(module);
+ if (std::strcmp(name, modName) == 0)
+ return true;
+ }
+ }
+ dec_frame.reset(PyObject_GetAttr(dec_frame, _f_back));
+ }
+ return false;
+}
+
+// PYSIDE-2404: These modules produce ambiguous names which we cannot handle, yet.
+static std::unordered_set<std::string> dontLazyLoad{
+ "sample",
+ "smart",
+ "testbinding"
+};
+
+static const std::unordered_set<std::string> knownModules{
+ "shiboken6.Shiboken",
+ "minimal",
+ "other",
+ "sample",
+ "smart",
+ "scriptableapplication",
+ "testbinding"
+};
+
+static bool canNotLazyLoad(PyObject *module)
+{
+ const char *modName = PyModule_GetName(module);
+
+ // There are no more things that must be disabled :-D
+ return dontLazyLoad.find(modName) != dontLazyLoad.end();
+}
+
+static bool shouldLazyLoad(PyObject *module)
+{
+ const char *modName = PyModule_GetName(module);
+
+ if (knownModules.find(modName) != knownModules.end())
+ return true;
+ return std::strncmp(modName, "PySide6.", 8) == 0;
+}
+
+void checkIfShouldLoadImmediately(PyObject *module, const std::string &name,
+ const NameToTypeFunctionMap &nameToFunc)
+{
+ static const char *flag = getenv("PYSIDE6_OPTION_LAZY");
+ static const int value = flag != nullptr ? std::atoi(flag) : 1;
+
+ // PYSIDE-2404: Lazy Loading
+ //
+ // Options:
+ // 0 - switch lazy loading off.
+ // 1 - lazy loading for all known modules.
+ // 3 - lazy loading for any module.
+ //
+ // By default we lazy load all known modules (option = 1).
+ if (value == 0 // completely disabled
+ || canNotLazyLoad(module) // for some reason we cannot lazy load
+ || (value == 1 && !shouldLazyLoad(module)) // not a known module
+ ) {
+ incarnateHelper(module, name, nameToFunc);
+ }
+}
+
+void AddTypeCreationFunction(PyObject *module,
+ const char *name,
+ TypeCreationFunction func)
+{
+ // - locate the module in the moduleTofuncs mapping
+ auto tableIter = moduleToFuncs.find(module);
+ assert(tableIter != moduleToFuncs.end());
+ // - Assign the name/generating function tcStruct.
+ auto &nameToFunc = tableIter->second;
+ TypeCreationStruct tcStruct{func, {}};
+ auto nit = nameToFunc.find(name);
+ if (nit == nameToFunc.end())
+ nameToFunc.insert(std::make_pair(name, tcStruct));
+ else
+ nit->second = tcStruct;
+
+ checkIfShouldLoadImmediately(module, name, nameToFunc);
+}
+
+void AddTypeCreationFunction(PyObject *module,
+ const char *containerName,
+ TypeCreationFunction func,
+ const char *namePath)
+{
+ // - locate the module in the moduleTofuncs mapping
+ auto tableIter = moduleToFuncs.find(module);
+ assert(tableIter != moduleToFuncs.end());
+ // - Assign the name/generating function tcStruct.
+ auto &nameToFunc = tableIter->second;
+ auto nit = nameToFunc.find(containerName);
+
+ // - insert namePath into the subtype vector of the main type.
+ nit->second.subtypeNames.push_back(namePath);
+ // - insert it also as its own entry.
+ nit = nameToFunc.find(namePath);
+ TypeCreationStruct tcStruct{func, {}};
+ if (nit == nameToFunc.end())
+ nameToFunc.insert(std::make_pair(namePath, tcStruct));
+ else
+ nit->second = tcStruct;
+
+ checkIfShouldLoadImmediately(module, namePath, nameToFunc);
+}
+
PyObject *import(const char *moduleName)
{
PyObject *sysModules = PyImport_GetModuleDict();
PyObject *module = PyDict_GetItemString(sysModules, moduleName);
- if (module)
+ if (module != nullptr)
Py_INCREF(module);
else
module = PyImport_ImportModule(moduleName);
- if (!module)
- PyErr_Format(PyExc_ImportError,"could not import module '%s'", moduleName);
+ if (module == nullptr)
+ PyErr_Format(PyExc_ImportError, "could not import module '%s'", moduleName);
return module;
}
-PyObject *create(const char *moduleName, void *moduleData)
+// PYSIDE-2404: Redirecting import for "import *" support.
+//
+// The first import will be handled by the isImportStar function.
+// But the same module might be imported twice, which would give no
+// introspection due to module caching.
+
+static PyObject *origImportFunc{};
+
+static PyObject *lazy_import(PyObject * /* self */, PyObject *args, PyObject *kwds)
+{
+ auto *ret = PyObject_Call(origImportFunc, args, kwds);
+ if (ret != nullptr) {
+ // PYSIDE-2404: Support star import when lazy loading.
+ if (PyTuple_Size(args) >= 4) {
+ auto *fromlist = PyTuple_GetItem(args, 3);
+ if (PyTuple_Check(fromlist) && PyTuple_Size(fromlist) == 1
+ && Shiboken::String::toCString(PyTuple_GetItem(fromlist, 0))[0] == '*')
+ Shiboken::Module::resolveLazyClasses(ret);
+ }
+ }
+ return ret;
+}
+
+static PyMethodDef lazy_methods[] = {
+ {"__lazy_import__", (PyCFunction)lazy_import, METH_VARARGS | METH_KEYWORDS, nullptr},
+ {nullptr, nullptr, 0, nullptr}
+};
+
+PyObject *create(const char * /* modName */, void *moduleData)
{
+ static auto *sysModules = PyImport_GetModuleDict();
+ static auto *builtins = PyEval_GetBuiltins();
+ static auto *partial = Pep_GetPartialFunction();
+ static bool lazy_init{};
+
Shiboken::init();
- return PyModule_Create(reinterpret_cast<PyModuleDef *>(moduleData));
+ auto *module = PyModule_Create(reinterpret_cast<PyModuleDef *>(moduleData));
+
+ // Setup of a dir function for "missing" classes.
+ auto *moduleDirTemplate = PyCFunction_NewEx(module_methods, nullptr, nullptr);
+ // Turn this function into a bound object, so we have access to the module.
+ auto *moduleDir = PyObject_CallFunctionObjArgs(partial, moduleDirTemplate, module, nullptr);
+ PyModule_AddObject(module, module_methods->ml_name, moduleDir); // steals reference
+ // Insert an initial empty table for the module.
+ NameToTypeFunctionMap empty;
+ moduleToFuncs.insert(std::make_pair(module, empty));
+
+ // A star import must be done unconditionally. Use the complete name.
+ if (isImportStar(module))
+ dontLazyLoad.insert(PyModule_GetName(module));
+
+ if (!lazy_init) {
+ // Install the getattr patch.
+ origModuleGetattro = PyModule_Type.tp_getattro;
+ PyModule_Type.tp_getattro = PyModule_lazyGetAttro;
+ // Add the lazy import redirection.
+ origImportFunc = PyDict_GetItemString(builtins, "__import__");
+ auto *func = PyCFunction_NewEx(lazy_methods, nullptr, nullptr);
+ PyDict_SetItemString(builtins, "__import__", func);
+ // Everything is set.
+ lazy_init = true;
+ }
+ // PYSIDE-2404: Nuitka inserts some additional code in standalone mode
+ // in an invisible virtual module (i.e. `QtCore-postLoad`)
+ // that gets imported before the running import can call
+ // `_PyImport_FixupExtensionObject` which does the insertion
+ // into `sys.modules`. This can cause a race condition.
+ // Insert the module early into the module dict to prevend recursion.
+ PyDict_SetItemString(sysModules, PyModule_GetName(module), module);
+ return module;
}
-void registerTypes(PyObject *module, PyTypeObject **types)
+void registerTypes(PyObject *module, TypeInitStruct *types)
{
auto iter = moduleTypes.find(module);
if (iter == moduleTypes.end())
moduleTypes.insert(std::make_pair(module, types));
}
-PyTypeObject **getTypes(PyObject *module)
+TypeInitStruct *getTypes(PyObject *module)
{
auto iter = moduleTypes.find(module);
return (iter == moduleTypes.end()) ? 0 : iter->second;
diff --git a/sources/shiboken6/libshiboken/sbkmodule.h b/sources/shiboken6/libshiboken/sbkmodule.h
index a4f7837f5..1b3de33b7 100644
--- a/sources/shiboken6/libshiboken/sbkmodule.h
+++ b/sources/shiboken6/libshiboken/sbkmodule.h
@@ -12,8 +12,22 @@ extern "C"
struct SbkConverter;
}
-namespace Shiboken {
-namespace Module {
+namespace Shiboken::Module {
+
+struct TypeInitStruct
+{
+ PyTypeObject *type;
+ const char *fullName;
+};
+
+/// PYSIDE-2404: Replacing the arguments in cpythonTypeNameExt by a function.
+LIBSHIBOKEN_API PyTypeObject *get(TypeInitStruct &typeStruct);
+
+/// PYSIDE-2404: Make sure that mentioned classes really exist.
+LIBSHIBOKEN_API void loadLazyClassesWithName(const char *name);
+
+/// PYSIDE-2404: incarnate all classes for star imports.
+LIBSHIBOKEN_API void resolveLazyClasses(PyObject *module);
/**
* Imports and returns the module named \p moduleName, or a NULL pointer in case of failure.
@@ -30,19 +44,43 @@ LIBSHIBOKEN_API PyObject *import(const char *moduleName);
*/
LIBSHIBOKEN_API PyObject *create(const char *moduleName, void *moduleData);
+using TypeCreationFunction = PyTypeObject *(*)(PyObject *module);
+
+/// Adds a type creation function to the module.
+LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module,
+ const char *name,
+ TypeCreationFunction func);
+
+LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module,
+ const char *name,
+ TypeCreationFunction func,
+ const char *containerName);
+
+LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module,
+ const char *name,
+ TypeCreationFunction func,
+ const char *outerContainerName,
+ const char *innerContainerName);
+
+LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module,
+ const char *name,
+ TypeCreationFunction func,
+ const char *containerName3,
+ const char *containerName2,
+ const char *containerName);
/**
* Registers the list of types created by \p module.
* \param module Module where the types were created.
* \param types Array of PyTypeObject *objects representing the types created on \p module.
*/
-LIBSHIBOKEN_API void registerTypes(PyObject *module, PyTypeObject **types);
+LIBSHIBOKEN_API void registerTypes(PyObject *module, TypeInitStruct *types);
/**
* Retrieves the array of types.
* \param module Module where the types were created.
* \returns A pointer to the PyTypeObject *array of types.
*/
-LIBSHIBOKEN_API PyTypeObject **getTypes(PyObject *module);
+LIBSHIBOKEN_API TypeInitStruct *getTypes(PyObject *module);
/**
* Registers the list of converters created by \p module for non-wrapper types.
@@ -58,6 +96,6 @@ LIBSHIBOKEN_API void registerTypeConverters(PyObject *module, SbkConverter **con
*/
LIBSHIBOKEN_API SbkConverter **getTypeConverters(PyObject *module);
-} } // namespace Shiboken::Module
+} // namespace Shiboken::Module
#endif // SBK_MODULE_H
diff --git a/sources/shiboken6/libshiboken/sbknumpy.cpp b/sources/shiboken6/libshiboken/sbknumpy.cpp
index 46b3af702..b6422e73f 100644
--- a/sources/shiboken6/libshiboken/sbknumpy.cpp
+++ b/sources/shiboken6/libshiboken/sbknumpy.cpp
@@ -7,17 +7,40 @@
# include <numpy/arrayobject.h>
#endif
+#include "helper.h"
#include "sbknumpycheck.h"
+#include "sbkcpptonumpy.h"
#include "sbknumpyview.h"
+#include <algorithm>
+
namespace Shiboken::Numpy
{
+#ifdef HAVE_NUMPY
+static void initNumPy()
+{
+ // PYSIDE-2404: Delay-initialize numpy from check() as it causes a
+ // significant startup delay (~770 allocations in memray)
+ static bool initialized = false;
+ if (initialized)
+ return;
+ initialized = true;
+ // Expanded from macro "import_array" in __multiarray_api.h
+ // Make sure to read about the magic defines PY_ARRAY_UNIQUE_SYMBOL etc.,
+ // when changing this or spreading the code over several source files.
+ if (_import_array() < 0)
+ PyErr_Print();
+}
+#endif // HAVE_NUMPY
+
bool check(PyObject *pyIn)
{
#ifdef HAVE_NUMPY
+ initNumPy();
return PyArray_Check(pyIn);
#else
+ SBK_UNUSED(pyIn);
return false;
#endif
}
@@ -28,6 +51,7 @@ bool check(PyObject *pyIn)
// translation unit (see comment at initNumPyArrayConverters()).
#include "sbknumpyview.cpp"
+#include "sbkcpptonumpy.cpp"
#ifdef HAVE_NUMPY
# include "sbknumpyarrayconverter.cpp"
#endif
diff --git a/sources/shiboken6/libshiboken/sbknumpyarrayconverter.cpp b/sources/shiboken6/libshiboken/sbknumpyarrayconverter.cpp
index c8541adf5..835a97524 100644
--- a/sources/shiboken6/libshiboken/sbknumpyarrayconverter.cpp
+++ b/sources/shiboken6/libshiboken/sbknumpyarrayconverter.cpp
@@ -94,8 +94,7 @@ std::ostream &operator<<(std::ostream &str, PyArrayObject *o)
return str;
}
-namespace Shiboken {
-namespace Conversions {
+namespace Shiboken::Conversions {
// Internals from sbkarrayconverter.cpp
SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc);
@@ -105,6 +104,7 @@ SbkArrayConverter *unimplementedArrayConverter();
template <int dimension>
static bool isPrimitiveArray(PyObject *pyIn, int expectedNpType)
{
+ Shiboken::Numpy::initNumPy();
if (!PyArray_Check(pyIn))
return false;
auto *pya = reinterpret_cast<PyArrayObject *>(pyIn);
@@ -210,6 +210,9 @@ static PythonToCppFunc checkArray2(PyObject *pyIn, int dim1, int dim2)
template <class T>
static void setOrExtendArrayConverter(int dimension, IsArrayConvertibleToCppFunc toCppCheckFunc)
{
+ // PYSIDE-2404/FIXME: When adding a C++ -> Python conversion, be sure
+ // to delay-initialize numpy in the converter (similar to the
+ // initialization in check() for the Python -> C++ conversion).
SbkArrayConverter *arrayConverter = ArrayTypeConverter<T>(dimension);
if (arrayConverter == unimplementedArrayConverter()) {
arrayConverter = createArrayConverter(toCppCheckFunc);
@@ -235,15 +238,6 @@ static inline void extendArrayConverter2()
void initNumPyArrayConverters()
{
- // Expanded from macro "import_array" in __multiarray_api.h
- // Make sure to read about the magic defines PY_ARRAY_UNIQUE_SYMBOL etc.,
- // when changing this or spreading the code over several source files.
- if (_import_array() < 0) {
- if (debugNumPy)
- PyErr_Print();
- PyErr_Clear();
- return;
- }
// Extend the converters for primitive types by NumPy ones.
extendArrayConverter1<short, NPY_SHORT>();
extendArrayConverter2<short, NPY_SHORT>();
@@ -273,5 +267,4 @@ void initNumPyArrayConverters()
extendArrayConverter2<double, NPY_DOUBLE>();
}
-} // namespace Conversions
-} // namespace Shiboken
+} // namespace Shiboken::Conversions
diff --git a/sources/shiboken6/libshiboken/sbknumpyview.cpp b/sources/shiboken6/libshiboken/sbknumpyview.cpp
index 44a4b5587..bafbf8038 100644
--- a/sources/shiboken6/libshiboken/sbknumpyview.cpp
+++ b/sources/shiboken6/libshiboken/sbknumpyview.cpp
@@ -6,12 +6,54 @@
#include "helper.h"
#include <iostream>
#include <iomanip>
+#include <optional>
#ifdef HAVE_NUMPY
namespace Shiboken {
namespace Numpy {
+static std::optional<View::Type> viewTypeFromNumPy(int npt)
+{
+ switch (npt) {
+ case NPY_SHORT:
+ return View::Int16;
+ case NPY_USHORT:
+ return View::Unsigned16;
+ case NPY_INT:
+ return View::Int;
+ case NPY_UINT:
+ return View::Unsigned;
+ case NPY_LONG:
+ if constexpr (sizeof(long) == sizeof(int))
+ return View::Int;
+ if constexpr (sizeof(long) == sizeof(int64_t))
+ return View::Int64;
+ break;
+ case NPY_ULONG:
+ if constexpr (sizeof(long) == sizeof(int))
+ return View::Unsigned;
+ if constexpr (sizeof(long) == sizeof(int64_t))
+ return View::Unsigned64;
+ break;
+ case NPY_LONGLONG:
+ if constexpr (sizeof(long long) == 8)
+ return View::Int64;
+ break;
+ case NPY_ULONGLONG:
+ if constexpr (sizeof(long long) == 8)
+ return View::Unsigned64;
+ break;
+ case NPY_FLOAT:
+ return View::Float;
+ case NPY_DOUBLE:
+ return View::Double;
+ default:
+ break;
+ }
+ return {};
+}
+
View View::fromPyObject(PyObject *pyIn)
{
if (pyIn == nullptr || PyArray_Check(pyIn) == 0)
@@ -23,27 +65,13 @@ View View::fromPyObject(PyObject *pyIn)
if (ndim > 2)
return {};
- View::Type type;
- switch (PyArray_TYPE(ar)) {
- case NPY_INT:
- type = View::Int;
- break;
- case NPY_UINT:
- type = View::Unsigned;
- break;
- case NPY_FLOAT:
- type = View::Float;
- break;
- case NPY_DOUBLE:
- type = View::Double;
- break;
- default:
+ const auto typeO = viewTypeFromNumPy(PyArray_TYPE(ar));
+ if (!typeO.has_value())
return {};
- }
View result;
result.ndim = ndim;
- result.type = type;
+ result.type = typeO.value();
result.data = PyArray_DATA(ar);
result.dimensions[0] = PyArray_DIMS(ar)[0];
result.stride[0] = PyArray_STRIDES(ar)[0];
@@ -91,11 +119,29 @@ std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &a)
}
str << "], type=";
switch (type) {
+ case NPY_SHORT:
+ str << "short";
+ break;
+ case NPY_USHORT:
+ str << "ushort";
+ break;
case NPY_INT:
- str << "int";
+ str << "int32";
break;
case NPY_UINT:
- str << "uint";
+ str << "uint32";
+ break;
+ case NPY_LONG:
+ str << "long";
+ break;
+ case NPY_ULONG:
+ str << "ulong";
+ break;
+ case NPY_LONGLONG:
+ str << "long long";
+ break;
+ case NPY_ULONGLONG:
+ str << "ulong long";
break;
case NPY_FLOAT:
str << "float";
@@ -122,12 +168,30 @@ std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &a)
if (const int dim0 = PyArray_DIMS(ar)[0]) {
auto *data = PyArray_DATA(ar);
switch (type) {
+ case NPY_SHORT:
+ debugArray(str, reinterpret_cast<const short *>(data), dim0);
+ break;
+ case NPY_USHORT:
+ debugArray(str, reinterpret_cast<const unsigned short *>(data), dim0);
+ break;
case NPY_INT:
debugArray(str, reinterpret_cast<const int *>(data), dim0);
break;
case NPY_UINT:
debugArray(str, reinterpret_cast<const unsigned *>(data), dim0);
break;
+ case NPY_LONG:
+ debugArray(str, reinterpret_cast<const long *>(data), dim0);
+ break;
+ case NPY_ULONG:
+ debugArray(str, reinterpret_cast<const unsigned long*>(data), dim0);
+ break;
+ case NPY_LONGLONG:
+ debugArray(str, reinterpret_cast<const long long *>(data), dim0);
+ break;
+ case NPY_ULONGLONG:
+ debugArray(str, reinterpret_cast<const unsigned long long *>(data), dim0);
+ break;
case NPY_FLOAT:
debugArray(str, reinterpret_cast<const float *>(data), dim0);
break;
diff --git a/sources/shiboken6/libshiboken/sbknumpyview.h b/sources/shiboken6/libshiboken/sbknumpyview.h
index d41e2c716..918913b78 100644
--- a/sources/shiboken6/libshiboken/sbknumpyview.h
+++ b/sources/shiboken6/libshiboken/sbknumpyview.h
@@ -22,7 +22,7 @@ LIBSHIBOKEN_API bool check(PyObject *pyIn);
/// numpy headers.
struct LIBSHIBOKEN_API View
{
- enum Type { Int, Unsigned, Float, Double};
+ enum Type { Int, Unsigned, Float, Double, Int16, Unsigned16, Int64, Unsigned64 };
static View fromPyObject(PyObject *pyIn);
diff --git a/sources/shiboken6/libshiboken/sbkpython.h b/sources/shiboken6/libshiboken/sbkpython.h
index e8fa29cbb..e62fa13ae 100644
--- a/sources/shiboken6/libshiboken/sbkpython.h
+++ b/sources/shiboken6/libshiboken/sbkpython.h
@@ -5,7 +5,6 @@
#define SBKPYTHON_H
#include "sbkversion.h"
-#define PyEnumMeta_Check(x) (strcmp(Py_TYPE(x)->tp_name, "EnumMeta") == 0)
// Qt's "slots" macro collides with the "slots" member variables
// used in some Python structs. For compilers that support push_macro,
diff --git a/sources/shiboken6/libshiboken/sbksmartpointer.cpp b/sources/shiboken6/libshiboken/sbksmartpointer.cpp
new file mode 100644
index 000000000..ee28f7db8
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbksmartpointer.cpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "sbksmartpointer.h"
+#include "sbkstring.h"
+#include "autodecref.h"
+
+#include <unordered_set>
+
+namespace Shiboken::SmartPointer
+{
+
+PyObject *repr(PyObject *pointer, PyObject *pointee)
+{
+ Shiboken::AutoDecRef pointerRepr(Shiboken::String::repr(pointer));
+ if (pointer == nullptr)
+ return pointerRepr.release();
+
+ Shiboken::AutoDecRef pointeeRepr(pointee != nullptr
+ ? PyObject_Repr(pointee)
+ : Shiboken::String::repr(pointee));
+
+ return PyUnicode_FromFormat("%U (%U)", pointerRepr.object(), pointeeRepr.object());
+}
+
+// __dir__ for a smart pointer. Add the __dir__ entries of the pointee to the list.
+PyObject *dir(PyObject *pointer, PyObject *pointee)
+{
+ if (pointer == nullptr)
+ return PyList_New(0);
+ // Get the pointer's dir entries. Note: PyObject_Dir() cannot be called on
+ // self, will crash. Work around by using the type dict keys.
+ AutoDecRef tpDict(PepType_GetDict(Py_TYPE(pointer)));
+ auto *result = PyMapping_Keys(tpDict);
+
+ if (pointee != nullptr && pointee != Py_None) {
+ // Add the entries of the pointee that do not exist in the pointer's list.
+ // Since Python internally caches strings; we can use a set of PyObject *.
+ std::unordered_set<PyObject *> knownStrings;
+ for (Py_ssize_t i = 0, size = PySequence_Size(result); i < size; ++i) {
+ Shiboken::AutoDecRef item(PySequence_GetItem(result, i));
+ knownStrings.insert(item.object());
+ }
+ const auto knownEnd = knownStrings.end();
+
+ Shiboken::AutoDecRef pointeeDir(PyObject_Dir(pointee));
+ for (Py_ssize_t i = 0, size = PySequence_Size(pointeeDir.object()); i < size; ++i) {
+ Shiboken::AutoDecRef item(PySequence_GetItem(pointeeDir, i));
+ if (knownStrings.find(item.object()) == knownEnd)
+ PyList_Append(result, item.object());
+ }
+ }
+
+ PyList_Sort(result);
+ return result;
+}
+
+} // namespace Shiboken::SmartPointer
diff --git a/sources/shiboken6/libshiboken/sbksmartpointer.h b/sources/shiboken6/libshiboken/sbksmartpointer.h
new file mode 100644
index 000000000..5e2022722
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbksmartpointer.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef SBK_SBKSMARTPOINTER_H
+#define SBK_SBKSMARTPOINTER_H
+
+#include "sbkpython.h"
+#include "shibokenmacros.h"
+
+namespace Shiboken::SmartPointer
+{
+
+LIBSHIBOKEN_API PyObject *repr(PyObject *pointer, PyObject *pointee);
+LIBSHIBOKEN_API PyObject *dir(PyObject *pointer, PyObject *pointee);
+
+} // namespace Shiboken::SmartPointer
+
+#endif // SBK_SBKSMARTPOINTER_H
diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
index 3f2484f31..023de0ea4 100644
--- a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
+++ b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
@@ -24,6 +24,7 @@ STATIC_STRING_IMPL(im_self, "im_self")
STATIC_STRING_IMPL(loads, "loads")
STATIC_STRING_IMPL(multi, "multi")
STATIC_STRING_IMPL(name, "name")
+STATIC_STRING_IMPL(orig_dict, "orig_dict")
STATIC_STRING_IMPL(qApp, "qApp")
STATIC_STRING_IMPL(result, "result")
STATIC_STRING_IMPL(select_id, "select_id")
@@ -75,8 +76,13 @@ STATIC_STRING_IMPL(iter, "__iter__")
STATIC_STRING_IMPL(mro, "__mro__")
STATIC_STRING_IMPL(new_, "__new__")
STATIC_STRING_IMPL(objclass, "__objclass__")
-STATIC_STRING_IMPL(signature, "__signature__")
STATIC_STRING_IMPL(weakrefoffset, "__weakrefoffset__")
STATIC_STRING_IMPL(opaque_container, "__opaque_container__")
} // namespace PyMagicName
+
+namespace Messages
+{
+STATIC_STRING_IMPL(unknownException, "An unknown exception was caught")
+}
+
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.h b/sources/shiboken6/libshiboken/sbkstaticstrings.h
index c89fdc9cd..017790ee3 100644
--- a/sources/shiboken6/libshiboken/sbkstaticstrings.h
+++ b/sources/shiboken6/libshiboken/sbkstaticstrings.h
@@ -23,6 +23,7 @@ LIBSHIBOKEN_API PyObject *im_self();
LIBSHIBOKEN_API PyObject *loads();
LIBSHIBOKEN_API PyObject *multi();
LIBSHIBOKEN_API PyObject *name();
+LIBSHIBOKEN_API PyObject *orig_dict();
LIBSHIBOKEN_API PyObject *result();
LIBSHIBOKEN_API PyObject *select_id();
LIBSHIBOKEN_API PyObject *value();
@@ -50,6 +51,11 @@ LIBSHIBOKEN_API PyObject *code();
LIBSHIBOKEN_API PyObject *rlshift();
LIBSHIBOKEN_API PyObject *rrshift();
} // namespace PyMagicName
+
+namespace Messages
+{
+LIBSHIBOKEN_API PyObject *unknownException();
+} // Messages
} // namespace Shiboken
#endif // SBKSTATICSTRINGS_H
diff --git a/sources/shiboken6/libshiboken/sbkstring.cpp b/sources/shiboken6/libshiboken/sbkstring.cpp
index 8f2dc6d52..1471cd7fe 100644
--- a/sources/shiboken6/libshiboken/sbkstring.cpp
+++ b/sources/shiboken6/libshiboken/sbkstring.cpp
@@ -233,4 +233,16 @@ PyObject *getSnakeCaseName(PyObject *name, bool lower)
return name;
}
+// Return a generic representation of a PyObject as does PyObject_Repr().
+// Note: PyObject_Repr() may not be called on self from __repr__() as this
+// causes a recursion.
+PyObject *repr(PyObject *o)
+{
+ if (o == nullptr)
+ return PyUnicode_FromString("<NULL>");
+ if (o == Py_None)
+ return PyUnicode_FromString("None");
+ return PyUnicode_FromFormat("<%s object at %p>", Py_TYPE(o)->tp_name, o);
+}
+
} // namespace Shiboken::String
diff --git a/sources/shiboken6/libshiboken/sbkstring.h b/sources/shiboken6/libshiboken/sbkstring.h
index a24c01def..f91847c11 100644
--- a/sources/shiboken6/libshiboken/sbkstring.h
+++ b/sources/shiboken6/libshiboken/sbkstring.h
@@ -29,6 +29,7 @@ namespace String
LIBSHIBOKEN_API PyObject *createStaticString(const char *str);
LIBSHIBOKEN_API PyObject *getSnakeCaseName(const char *name, bool lower);
LIBSHIBOKEN_API PyObject *getSnakeCaseName(PyObject *name, bool lower);
+ LIBSHIBOKEN_API PyObject *repr(PyObject *o);
} // namespace String
} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/sbktypefactory.cpp b/sources/shiboken6/libshiboken/sbktypefactory.cpp
index 0da1a8e23..079548eed 100644
--- a/sources/shiboken6/libshiboken/sbktypefactory.cpp
+++ b/sources/shiboken6/libshiboken/sbktypefactory.cpp
@@ -7,6 +7,8 @@
extern "C"
{
+using Shiboken::AutoDecRef;
+
PyTypeObject *SbkType_FromSpec(PyType_Spec *spec)
{
return SbkType_FromSpec_BMDWB(spec, nullptr, nullptr, 0, 0, nullptr);
@@ -37,6 +39,60 @@ static PyObject *_PyType_FromSpecWithBases(PyType_Spec *, PyObject *);
#endif // PYPY_VERSION
+// PYSIDE-2230: Not so temporary fix for Python 3.12.
+// A tp_new is no longer allowed in a meta class.
+// Hopefully, the Python devs will supply the missing support.
+// It turned out that they will not fix that, as expected.
+// Note: Python 3.12 is the first version that grabs the metaclass from base classes.
+static PyObject *_PyType_FromSpecWithBasesHack(PyType_Spec *spec,
+ PyObject *bases,
+ PyTypeObject *meta)
+{
+ PyTypeObject *keepMeta{};
+ newfunc keepNew{};
+ AutoDecRef basesPatch{};
+
+ if (bases) {
+ if (bases == Py_None) {
+ // PYSIDE-2230: This is the SbkObject entry which has no base to provide
+ // the metaclass. We patch it in by modifying `object`s class.
+ assert(meta);
+ auto *base = reinterpret_cast<PyObject *>(&PyBaseObject_Type);
+ base->ob_type = meta;
+ basesPatch.reset(Py_BuildValue("(O)", &PyBaseObject_Type));
+ bases = basesPatch.object();
+ }
+
+ Py_ssize_t n = PyTuple_GET_SIZE(bases);
+ for (auto idx = 0; idx < n; ++idx) {
+ PyTypeObject *base = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, idx));
+ PyTypeObject *meta = Py_TYPE(base);
+ if (meta->tp_new != PyType_Type.tp_new) {
+ // make sure there is no second meta class
+ assert(keepMeta == nullptr);
+ keepMeta = meta;
+ keepNew = meta->tp_new;
+ meta->tp_new = PyType_Type.tp_new;
+ }
+ }
+ }
+
+#if !defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x030C0000
+ auto *ret = PyType_FromMetaclass(meta, nullptr /*module*/, spec, bases);
+#else
+ auto *ret = _PyType_FromSpecWithBases(spec, bases);
+#endif
+
+ if (keepMeta)
+ keepMeta->tp_new = keepNew;
+ if (basesPatch.object()) {
+ // undo the metaclass patch.
+ auto *base = PyTuple_GET_ITEM(basesPatch.object(), 0);
+ base->ob_type = &PyType_Type;
+ }
+ return ret;
+}
+
PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
PyObject *bases,
PyTypeObject *meta,
@@ -61,7 +117,7 @@ PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
int package_level = atoi(spec->name);
const char *mod = new_spec.name = colon + 1;
- PyObject *obType = _PyType_FromSpecWithBases(&new_spec, bases);
+ PyObject *obType = _PyType_FromSpecWithBasesHack(&new_spec, bases, meta);
if (obType == nullptr)
return nullptr;
@@ -73,8 +129,8 @@ PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
qual = dot + 1;
}
int mlen = qual - mod - 1;
- Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
- Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual));
+ AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
+ AutoDecRef qualname(Shiboken::String::fromCString(qual));
auto *type = reinterpret_cast<PyTypeObject *>(obType);
@@ -98,9 +154,10 @@ PyTypeObject *SbkType_FromSpec_BMDWB(PyType_Spec *spec,
// PyType_Ready too early. (at least in PyPy, which caused pretty long debugging.)
auto *ht = reinterpret_cast<PyHeapTypeObject *>(type);
ht->ht_qualname = qualname;
- if (PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::qualname(), qualname))
+ AutoDecRef tpDict(PepType_GetDict(type));
+ if (PyDict_SetItem(tpDict.object(), Shiboken::PyMagicName::qualname(), qualname))
return nullptr;
- if (PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::module(), module))
+ if (PyDict_SetItem(tpDict.object(), Shiboken::PyMagicName::module(), module))
return nullptr;
PyType_Ready(type);
#else
@@ -329,7 +386,7 @@ _PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
/// Here is the only change needed: Do not finalize type creation.
// if (PyType_Ready(type) < 0)
// goto fail;
- type->tp_dict = PyDict_New();
+ PepType_SetDict(type, PyDict_New());
/// This is not found in PyPy:
// if (type->tp_dictoffset) {
// res->ht_cached_keys = _PyDict_NewKeysForClass();
diff --git a/sources/shiboken6/libshiboken/sbkversion.h.in b/sources/shiboken6/libshiboken/sbkversion.h.in
index 7f99abc3e..5c0b38fdb 100644
--- a/sources/shiboken6/libshiboken/sbkversion.h.in
+++ b/sources/shiboken6/libshiboken/sbkversion.h.in
@@ -10,8 +10,8 @@
#define SHIBOKEN_MICRO_VERSION @shiboken_MICRO_VERSION@
#define SHIBOKEN_RELEASE_LEVEL "final"
#define SHIBOKEN_SERIAL 0
-#define PYTHON_VERSION_MAJOR @PYTHON_VERSION_MAJOR@
-#define PYTHON_VERSION_MINOR @PYTHON_VERSION_MINOR@
-#define PYTHON_VERSION_PATCH @PYTHON_VERSION_PATCH@
+#define PYTHON_VERSION_MAJOR @Python_VERSION_MAJOR@
+#define PYTHON_VERSION_MINOR @Python_VERSION_MINOR@
+#define PYTHON_VERSION_PATCH @Python_VERSION_PATCH@
#endif
diff --git a/sources/shiboken6/libshiboken/sbkwindows.h b/sources/shiboken6/libshiboken/sbkwindows.h
new file mode 100644
index 000000000..9e753fa5e
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbkwindows.h
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef SBKWINDOWS_H
+#define SBKWINDOWS_H
+
+#ifdef _WIN32
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+#endif
+
+#endif // SBKWINDOWS_H
diff --git a/sources/shiboken6/libshiboken/shiboken.h b/sources/shiboken6/libshiboken/shiboken.h
index 13a15e1f4..fcf777ae0 100644
--- a/sources/shiboken6/libshiboken/shiboken.h
+++ b/sources/shiboken6/libshiboken/shiboken.h
@@ -11,10 +11,10 @@
#include "gilstate.h"
#include "threadstatesaver.h"
#include "helper.h"
+#include "pyobjectholder.h"
#include "sbkarrayconverter.h"
#include "sbkconverter.h"
#include "sbkenum.h"
-#include "sbkenum_p.h" // PYSIDE-1735: This is during the migration, only.
#include "sbkerrors.h"
#include "sbkmodule.h"
#include "sbkstring.h"
diff --git a/sources/shiboken6/libshiboken/signature.h b/sources/shiboken6/libshiboken/signature.h
index 94f234112..e0130b5a6 100644
--- a/sources/shiboken6/libshiboken/signature.h
+++ b/sources/shiboken6/libshiboken/signature.h
@@ -4,13 +4,15 @@
#ifndef SIGNATURE_H
#define SIGNATURE_H
+#include "shibokenmacros.h"
+#include "sbkpython.h"
+
extern "C"
{
LIBSHIBOKEN_API int InitSignatureStrings(PyTypeObject *, const char *[]);
LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *[]);
LIBSHIBOKEN_API void SetError_Argument(PyObject *, const char *, PyObject *);
-LIBSHIBOKEN_API PyObject *Sbk_TypeGet___signature__(PyObject *, PyObject *);
LIBSHIBOKEN_API PyObject *Sbk_TypeGet___doc__(PyObject *);
LIBSHIBOKEN_API PyObject *GetFeatureDict();
diff --git a/sources/shiboken6/libshiboken/signature/signature.cpp b/sources/shiboken6/libshiboken/signature/signature.cpp
index e70d79581..3255cb56d 100644
--- a/sources/shiboken6/libshiboken/signature/signature.cpp
+++ b/sources/shiboken6/libshiboken/signature/signature.cpp
@@ -13,13 +13,16 @@
// General documentation can be found in `signature_doc.rst`.
//
+#include "signature.h"
+#include "signature_p.h"
+
#include "basewrapper.h"
#include "autodecref.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
#include "sbkfeature_base.h"
-#include "signature_p.h"
+
#include <structmember.h>
using namespace Shiboken;
@@ -75,27 +78,24 @@ PyObject *GetTypeKey(PyObject *ob)
*
* PYSIDE-1286: We use correct __module__ and __qualname__, now.
*/
- // XXX we obtain also the current selection.
- // from the current module name.
AutoDecRef module_name(PyObject_GetAttr(ob, PyMagicName::module()));
if (module_name.isNull()) {
// We have no module_name because this is a module ;-)
PyErr_Clear();
module_name.reset(PyObject_GetAttr(ob, PyMagicName::name()));
- return Py_BuildValue("O"/*i"*/, module_name.object()/*, getFeatureSelectId()*/);
+ return Py_BuildValue("O", module_name.object());
}
AutoDecRef class_name(PyObject_GetAttr(ob, PyMagicName::qualname()));
if (class_name.isNull()) {
Py_FatalError("Signature: missing class name in GetTypeKey");
return nullptr;
}
- return Py_BuildValue("(O"/*i*/"O)", module_name.object(), /*getFeatureSelectId(),*/
- class_name.object());
+ return Py_BuildValue("(OO)", module_name.object(), class_name.object());
}
static PyObject *empty_dict = nullptr;
-PyObject *TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype)
+PyObject *TypeKey_to_PropsDict(PyObject *type_key)
{
PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, type_key);
if (dict == nullptr) {
@@ -143,7 +143,7 @@ PyObject *GetSignature_Method(PyObject *obfunc, PyObject *modifier)
AutoDecRef type_key(GetTypeKey(obtype_mod));
if (type_key.isNull())
Py_RETURN_NONE;
- PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod);
+ PyObject *dict = TypeKey_to_PropsDict(type_key);
if (dict == nullptr)
return nullptr;
AutoDecRef func_name(PyObject_GetAttr(obfunc, PyMagicName::name()));
@@ -163,7 +163,7 @@ PyObject *GetSignature_Function(PyObject *obfunc, PyObject *modifier)
AutoDecRef type_key(GetTypeKey(obtype_mod));
if (type_key.isNull())
Py_RETURN_NONE;
- PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod);
+ PyObject *dict = TypeKey_to_PropsDict(type_key);
if (dict == nullptr)
return nullptr;
AutoDecRef func_name(PyObject_GetAttr(obfunc, PyMagicName::name()));
@@ -191,13 +191,13 @@ PyObject *GetSignature_Wrapper(PyObject *ob, PyObject *modifier)
AutoDecRef class_key(GetTypeKey(objclass));
if (func_name.isNull() || objclass.isNull() || class_key.isNull())
return nullptr;
- PyObject *dict = TypeKey_to_PropsDict(class_key, objclass);
+ PyObject *dict = TypeKey_to_PropsDict(class_key);
if (dict == nullptr)
return nullptr;
PyObject *props = PyDict_GetItem(dict, func_name);
if (props == nullptr) {
// handle `__init__` like the class itself
- if (strcmp(String::toCString(func_name), "__init__") == 0)
+ if (PyUnicode_CompareWithASCIIString(func_name, "__init__") == 0)
return GetSignature_TypeMod(objclass, modifier);
Py_RETURN_NONE;
}
@@ -209,7 +209,7 @@ PyObject *GetSignature_TypeMod(PyObject *ob, PyObject *modifier)
AutoDecRef ob_name(PyObject_GetAttr(ob, PyMagicName::name()));
AutoDecRef ob_key(GetTypeKey(ob));
- PyObject *dict = TypeKey_to_PropsDict(ob_key, ob);
+ PyObject *dict = TypeKey_to_PropsDict(ob_key);
if (dict == nullptr)
return nullptr;
PyObject *props = PyDict_GetItem(dict, ob_name);
@@ -227,6 +227,8 @@ PyObject *GetSignature_TypeMod(PyObject *ob, PyObject *modifier)
// The `modifier` argument is a string that is passed in from `loader.py`.
// Configuration what the modifiers mean is completely in Python.
//
+// PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter.
+//
PyObject *get_signature_intern(PyObject *ob, PyObject *modifier)
{
@@ -246,6 +248,9 @@ PyObject *get_signature_intern(PyObject *ob, PyObject *modifier)
return pyside_tp_get___signature__(ob, modifier);
if (Py_TYPE(ob) == &PyWrapperDescr_Type)
return pyside_wd_get___signature__(ob, modifier);
+ // For classmethods we use the simple wrapper description implementation.
+ if (Py_TYPE(ob) == &PyClassMethodDescr_Type)
+ return pyside_wd_get___signature__(ob, modifier);
return nullptr;
}
@@ -254,8 +259,6 @@ static PyObject *get_signature(PyObject * /* self */, PyObject *args)
PyObject *ob;
PyObject *modifier = nullptr;
- init_module_1();
-
if (!PyArg_ParseTuple(args, "O|O", &ob, &modifier))
return nullptr;
if (Py_TYPE(ob) == PepFunction_TypePtr)
@@ -287,14 +290,25 @@ static PyObject *feature_import(PyObject * /* self */, PyObject *args, PyObject
if (import_func == nullptr) {
Py_FatalError("builtins has no \"__orig_import__\" function");
}
- return PyObject_Call(import_func, args, kwds);
+ ret = PyObject_Call(import_func, args, kwds);
+ if (ret) {
+ // PYSIDE-2029: Intercept after the import to search for PySide usage.
+ PyObject *post = PyObject_CallFunctionObjArgs(pyside_globals->feature_imported_func,
+ ret, nullptr);
+ Py_XDECREF(post);
+ if (post == nullptr) {
+ Py_DECREF(ret);
+ return nullptr;
+ }
+ }
+ return ret;
}
PyMethodDef signature_methods[] = {
- {"__feature_import__", (PyCFunction)feature_import, METH_VARARGS | METH_KEYWORDS},
+ {"__feature_import__", (PyCFunction)feature_import, METH_VARARGS | METH_KEYWORDS, nullptr},
{"get_signature", (PyCFunction)get_signature, METH_VARARGS,
- "get the __signature__, but pass an optional string parameter"},
- {nullptr, nullptr}
+ "get the signature, passing an optional string parameter"},
+ {nullptr, nullptr, 0, nullptr}
};
////////////////////////////////////////////////////////////////////////////
@@ -317,7 +331,6 @@ PyMethodDef signature_methods[] = {
static int PySide_BuildSignatureArgs(PyObject *obtype_mod, const char *signatures[])
{
- init_module_1();
AutoDecRef type_key(GetTypeKey(obtype_mod));
/*
* PYSIDE-996: Avoid string overflow in MSVC, which has a limit of
@@ -345,7 +358,6 @@ PyObject *PySide_BuildSignatureProps(PyObject *type_key)
* We simply pick up the arguments that we stored here and replace
* them by the function result.
*/
- init_module_2();
if (type_key == nullptr)
return nullptr;
PyObject *numkey = PyDict_GetItem(pyside_globals->arg_dict, type_key);
@@ -378,9 +390,7 @@ PyObject *PySide_BuildSignatureProps(PyObject *type_key)
#ifdef PYPY_VERSION
static bool get_lldebug_flag()
{
- PyObject *sysmodule = PyImport_AddModule("sys");
- auto *dic = PyModule_GetDict(sysmodule);
- dic = PyDict_GetItemString(dic, "pypy_translation_info");
+ auto *dic = PySys_GetObject("pypy_translation_info");
int lldebug = PyObject_IsTrue(PyDict_GetItemString(dic, "translation.lldebug"));
int lldebug0 = PyObject_IsTrue(PyDict_GetItemString(dic, "translation.lldebug0"));
return lldebug || lldebug0;
@@ -421,8 +431,6 @@ static int PySide_FinishSignatures(PyObject *module, const char *signatures[])
if (PyCFunction_Check(func))
if (PyDict_SetItem(pyside_globals->map_dict, func, module) < 0)
return -1;
- if (_finish_nested_classes(obdict) < 0)
- return -1;
// The finish_import function will not work the first time since phase 2
// was not yet run. But that is ok, because the first import is always for
// the shiboken module (or a test module).
@@ -444,9 +452,12 @@ static int PySide_FinishSignatures(PyObject *module, const char *signatures[])
int InitSignatureStrings(PyTypeObject *type, const char *signatures[])
{
+ // PYSIDE-2404: This function now also builds the mapping for static methods.
+ // It was one missing spot to let Lazy import work.
+ init_shibokensupport_module();
auto *ob_type = reinterpret_cast<PyObject *>(type);
int ret = PySide_BuildSignatureArgs(ob_type, signatures);
- if (ret < 0) {
+ if (ret < 0 || _build_func_to_type(ob_type) < 0) {
PyErr_Print();
PyErr_SetNone(PyExc_ImportError);
}
@@ -463,6 +474,8 @@ void FinishSignatureInitialization(PyObject *module, const char *signatures[])
* Still, it is not possible to call init phase 2 from here,
* because the import is still running. Do it from Python!
*/
+ init_shibokensupport_module();
+
#ifndef PYPY_VERSION
static const bool patch_types = true;
#else
@@ -526,8 +539,8 @@ static PyObject *adjustFuncName(const char *func_name)
// Find the feature flags
auto type = reinterpret_cast<PyTypeObject *>(obtype.object());
- auto dict = type->tp_dict;
- int id = SbkObjectType_GetReserved(type);
+ AutoDecRef dict(PepType_GetDict(type));
+ int id = currentSelectId(type);
id = id < 0 ? 0 : id; // if undefined, set to zero
auto lower = id & 0x01;
auto is_prop = id & 0x02;
@@ -550,33 +563,34 @@ static PyObject *adjustFuncName(const char *func_name)
if (prop_name) {
auto _prop_name = String::toCString(prop_name);
if (is_class_prop)
- sprintf(_buf, "%s.__dict__['%s'].fset", _path, _prop_name);
+ snprintf(_buf, sizeof(_buf), "%s.__dict__['%s'].fset", _path, _prop_name);
else
- sprintf(_buf, "%s.%s.fset", _path, _prop_name);
+ snprintf(_buf, sizeof(_buf), "%s.%s.fset", _path, _prop_name);
}
else {
auto _name = String::toCString(name);
- sprintf(_buf, "%s.%s", _path, _name);
+ snprintf(_buf, sizeof(_buf), "%s.%s", _path, _name);
}
return String::fromCString(_buf);
}
void SetError_Argument(PyObject *args, const char *func_name, PyObject *info)
{
+ init_shibokensupport_module();
/*
* This function replaces the type error construction with extra
* overloads parameter in favor of using the signature module.
* Error messages are rare, so we do it completely in Python.
*/
- init_module_1();
- init_module_2();
// PYSIDE-1305: Handle errors set by fillQtProperties.
if (PyErr_Occurred()) {
PyObject *e, *v, *t;
// Note: These references are all borrowed.
PyErr_Fetch(&e, &v, &t);
+ Py_DECREF(e);
info = v;
+ Py_XDECREF(t);
}
// PYSIDE-1019: Modify the function name expression according to feature.
AutoDecRef new_func_name(adjustFuncName(func_name));
@@ -607,21 +621,19 @@ void SetError_Argument(PyObject *args, const char *func_name, PyObject *info)
* But the __doc__ attribute existed already by inheritance, and calling
* PyType_Modified() is not supported. So we added the getsets explicitly
* to the metatype.
+ *
+ * PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter.
*/
-PyObject *Sbk_TypeGet___signature__(PyObject *ob, PyObject *modifier)
-{
- return pyside_tp_get___signature__(ob, modifier);
-}
-
PyObject *Sbk_TypeGet___doc__(PyObject *ob)
{
+ init_shibokensupport_module();
return pyside_tp_get___doc__(ob);
}
PyObject *GetFeatureDict()
{
- init_module_1();
+ init_shibokensupport_module();
return pyside_globals->feature_dict;
}
diff --git a/sources/shiboken6/libshiboken/signature/signature_doc.rst b/sources/shiboken6/libshiboken/signature/signature_doc.rst
deleted file mode 100644
index 0fb26ae52..000000000
--- a/sources/shiboken6/libshiboken/signature/signature_doc.rst
+++ /dev/null
@@ -1,376 +0,0 @@
-*************************
-The signature C extension
-*************************
-
-This module is a C extension for CPython 3.5 and up, and CPython 2.7.
-Its purpose is to provide support for the ``__signature__`` attribute
-of builtin PyCFunction objects.
-
-
-Short Introduction to the Topic
-===============================
-
-Beginning with CPython 3.5, Python functions began to grow a ``__signature__``
-attribute for normal Python functions. This is totally optional and just
-a nice-to-have feature in Python.
-
-PySide, on the other hand, could use ``__signature__`` very much, because the
-typing info for the 15000+ PySide functions is really missing, and it
-would be nice to have this info directly available.
-
-
-The Idea to Support Signatures
-==============================
-
-We want to have an additional ``__signature__`` attribute in all PySide
-methods, without changing lots of generated code.
-Therefore, we did not change any of the existing data structures,
-but supported the new attribute by a global dictionary.
-
-When the ``__signature__`` property is requested, a method is called that
-does a lookup in the global dict. This is a flexible approach with little impact
-to the rest of the project. It has very limited overhead compared to direct
-attribute access, but for the need of a signature access from time to time,
-this is an adequate compromise.
-
-
-How this Code Works
--------------------
-
-Signatures are supported for regular Python functions, only. Creating signatures
-for ``PyCFunction`` objects would require quite some extra effort in Python.
-
-Fortunately, we found this special *stealth* technique, that saves us most of the
-needed effort:
-
-The basic idea is to create a dummy Python function with **varnames**, **defaults**
-and **annotations** properties, and then to use the inspect
-module to create a signature object. This object is returned as the computed
-result of the ``__signature__`` attribute of the real ``PyCFunction`` object.
-
-There is one thing that really changes Python a bit:
-
-* We added the ``__signature__`` attribute to every function.
-
-That is a little change to Python that does not harm, but it saves us
-tons of code, that was needed in the early versions of the module.
-
-The internal work is done in two steps:
-
-* All functions of a class get the *signature text* when the module is imported.
- This is only a very small overhead added to the startup time. It is a single
- string for each whole class.
-* The actual signature object is created later, when the attribute is really
- requested. Signatures are cached and only created on first access.
-
-Example:
-
-The ``PyCFunction`` ``QtWidgets.QApplication.palette`` is interrogated for its
-signature. That means ``pyside_sm_get___signature__()`` is called.
-It calls ``GetSignature_Function`` which returns the signature if it is found.
-
-
-Why this Code is Fast
----------------------
-
-It costs a little time (maybe 6 seconds) to run through every single signature
-object, since these are more than 25000 Python objects. But all the signature
-objects will be rarely accessed but in special applications.
-The normal case are only a few accesses, and these are working pretty fast.
-
-The key to make this signature module fast is to avoid computation as much as
-possible. When no signature objects are used, then almost no time is lost in
-initialization. Only the above mentioned strings and some support modules are
-additionally loaded on ``import PySide6``.
-When it comes to signature usage, then late initialization is used and cached.
-This technique is also known as *full laziness* in haskell.
-
-There are actually two locations where late initialization occurs:
-
-* ``dict`` can be no dict but a tuple. That is the initial argument tuple that
- was saved by ``PySide_BuildSignatureArgs`` at module load time.
- If so, then ``pyside_type_init`` in parser.py will be called,
- which parses the string and creates the dict.
-* ``props`` can be empty. Then ``create_signature`` in loader.py
- is called, which uses a dummy function to produce a signature instance
- with the inspect module.
-
-The initialization that is always done is just two dictionary writes
-per class, and we have about 1000 classes.
-To measure the additional overhead, we have simulated what happens
-when ``from PySide6 import *`` is performed.
-It turned out that the overhead is below 0.5 ms.
-
-
-The Signature Package Structure
--------------------------------
-
-The C++ code involved with the signature module is completely in the file
-shiboken6/libshiboken/signature.cpp . All other functionality is implemented in
-the ``signature`` Python package. It has the following structure::
-
- shiboken6/files.dir/shibokensupport/
- backport_inspect.py
-
- signature/
- loader.py
- parser.py
- mapping.py
- errorhandler.py
- layout.py
-
- lib/
- enum_sig.py
- tool.py
-
-
-
-Really important are the **parser**, **mapping**, **errorhandler**, **enum_sig**,
-**layout** and **loader** modules. The rest is needed to create Python 2 compatibility
-or be compatible with embedding and installers.
-
-
-loader.py
-~~~~~~~~~
-
-This module assembles and imports the ``inspect`` module, and then exports the
-``create_signature`` function. This function takes a fake function and some
-attributes and builds a ``__signature__`` object with the inspect module.
-
-
-parser.py
-~~~~~~~~~
-
-This module takes a class signatures string from C++ and parses it into the
-needed properties for the ``create_signature`` function. Its entry point is the
-``pyside_type_init`` function, which is called from the C module via ``loader.py``.
-
-
-mapping.py
-~~~~~~~~~~
-
-The purpose of the mapping module is maintaining a list of replacement strings
-that map from the *signature text* in C to the property strings that Python
-needs. A lot of mappings are resolved by rather complex expressions in ``parser.py``,
-but a few hundred cases are better to spell explicitly, here.
-
-
-errorhandler.py
-~~~~~~~~~~~~~~~
-
-Since ``Qt For Python 5.12``, we no longer use the builtin type error messages from C++.
-Instead, we get much better results with the signature module. At the same time,
-this enforced supporting shiboken as well, and the signature module was no longer
-optional.
-
-
-enum_sig.py
-~~~~~~~~~~~
-
-The diverse applications of the signature module all needed to iterate over modules,
-classes and functions. In order to centralize this enumeration, the process has
-been factored out as a context manager. The user has only to supply functions
-that do the actual formatting.
-
-See for example the .pyi generator ``pyside6/PySide6/support/generate_pyi.py``.
-
-
-layout.py
-~~~~~~~~~
-
-As more applications used the signature module, different formatting of signatures
-was needed. To support that, we created the function ``create_signature``, which
-has a parameter to choose from some predefined layouts.
-
-
-*typing27.py*
-~~~~~~~~~~~~~
-
-Python 2 has no typing module at all. This is a backport of the minimum that is needed.
-
-
-*backport_inspect.py*
-~~~~~~~~~~~~~~~~~~~~~
-
-Python 2 has an inspect module, but lacks the signature functions, completely.
-This module adds the missing functionality, which is merged at runtime into
-the inspect module.
-
-
-Multiple Arities
-----------------
-
-One aspect that was ignored so far was *multiple arities*: How to handle it when
-a function has more than one signature?
-
-I did not find any note on how multiple signatures should be treated in Python,
-but this simple rules seem to work well:
-
-* If there is a list, then it is a multi-signature.
-* Otherwise, it is a simple signature.
-
-
-Impacts of The Signature Module
-===============================
-
-The signature module has a number of impacts to other PySide modules, which were
-created as a consequence of its existence, and there will be a few more in the
-future:
-
-
-existence_test.py
------------------
-
-The file ``pyside6/tests/registry/existence_test.py`` was written using the
-signatures from the signatures module. The idea is that there are some 15000
-functions with a certain signature.
-
-These functions should not get lost by some bad check-in. Therefore, a list
-of all existing signatures is kept as a module that assembles a
-dictionary. The function existence is checked, and also the exact arity.
-
-This module exists for every PySide release and every platform. The initial
-module is generated once and saved as ``exists_{plat}_{version}.py``.
-
-An error is normally only reported as a warning, but:
-
-
-Interaction With The Coin Module
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this test program is run in COIN, then the warnings are turned into
-errors. The reason is that only in COIN, we have a stable configuration
-of PySide modules that can reliably be compared.
-
-These modules have the name ``exists_{platf}_{version}_ci.py``, and as a big
-exception for generated code, these files are *intentionally* checked in.
-
-
-What Happens When a List is Missing?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When a new version of PySide gets created, then the existence test files
-initially do not exist.
-
-When a COIN test is run, then it will complain about the error and create
-the missing module on standard output.
-But since COIN tests are run multiple times, the output that was generated
-by the first test will still exist at the subsequent runs.
-(If COIN was properly implemented, we could not take that advantage and
-would need to implement that as an extra exception.)
-
-As a result, a missing module will be reported as a test which partially
-succeeded (called "FLAKY"). To avoid further flaky tests and to activate as a real test,
-we can now capture the error output of COIN and check the generated module
-in.
-
-
-Explicitly Enforcing Recreation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The former way to regenerate the registry files was to remove the files
-and check that in. This has the desired effect, but creates huge deltas.
-As a more efficient way, we have prepared a comment in the first line
-that contains the word "recreate".
-By uncommenting this line, a NameError is triggered, which has the same
-effect.
-
-
-init_platform.py
-~~~~~~~~~~~~~~~~
-
-For generating the ``exists_{platf}_{version}`` modules, the module
-``pyside6/tests/registry/init_platform.py`` was written. It can be used
-standalone from the commandline, to check the compatibility of some
-changes, directly.
-
-
-scrape_testresults.py
----------------------
-
-To simplify and automate the process of extracting the ``exists_{platf}_{version}_ci.py``
-files, the script ``pyside6/tests/registry/scrape_testresults.py`` has been written.
-
-This script scans the whole testresults website for PySide, that is::
-
- https://testresults.qt.io/coin/api/results/pyside/pyside-setup/
-
-On the first scan, the script runs less than 30 minutes. After that, a cache
-is generated and the scan works *much* faster. The test results are placed
-into the folder ``pyside6/tests/registry/testresults/embedded/`` with a
-unique name that allows for easy sorting. Example::
-
- testresults/embedded/2018_09_10_10_40_34-test_1536891759-exists_linux_5_11_2_ci.py
-
-These files are created only once. If they already exist, they are not touched, again.
-The file `pyside6/tests/registry/known_urls.json`` holds all scanned URLs after
-a successful scan. The ``testresults/embedded`` folder can be kept for reference
-or can be removed. Important is only the json file.
-
-The result of a scan is then directly placed into the ``pyside6/tests/registry/``
-folder. It should be reviewed and then eventually checked in.
-
-
-generate_pyi.py
----------------
-
-``pyside6/PySide6/support/generate_pyi.py`` is still under development.
-This module generates so-called hinting stubs for integration of PySide
-with diverse *Python IDEs*.
-
-Although this module creates the stubs as an add-on, the
-impact on the quality of the signature module is considerable:
-
-The module must create syntactically correct ``.pyi`` files which contain
-not only signatures but also constants and enums of all PySide modules.
-This serves as an extra challenge that has a very positive effect on
-the completeness and correctness of signatures.
-
-The module has a ``--feature`` option to generate modified .pyi files.
-A shortcut for this command is ``pyside6-genpyi``.
-
-A useful command to change all .pyi files to use all features is
-
-.. code-block:: python
-
- pyside6-genpyi all --feature snake_case true_property
-
-
-pyi_generator.py
-----------------
-
-``shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py``
-has been extracted from ``generate_pyi.py``. It allows the generation of ``.pyi``
-files from arbitrary extension modules created with shiboken.
-
-A shortcut for this command is ``shiboken6-genpyi``.
-
-
-Current Extensions
-------------------
-
-Before the signature module was written, there already existed the concept of
-signatures, but in a more C++ - centric way. From that time, there existed
-the error messages, which are created when a function gets wrong argument types.
-
-These error messages were replaced by text generated on demand by
-the signature module, in order to be more consistent and correct.
-This was implemented in ``Qt For Python 5.12.0``.
-
-Additionally, the ``__doc__`` attribute of PySide methods was not set.
-It was easy to get a nice ``help()`` feature by creating signatures
-as default content for docstrings.
-This was implemented in ``Qt For Python 5.12.1``.
-
-
-Literature
-==========
-
- `PEP 362 – Function Signature Object <https://www.python.org/dev/peps/pep-0362/>`__
-
- `PEP 484 – Type Hints <https://www.python.org/dev/peps/pep-0484/>`__
-
- `PEP 3107 – Function Annotations <https://www.python.org/dev/peps/pep-3107/>`__
-
-
-*Personal Remark: This module is dedicated to our lovebird "Püppi", who died on 2017-09-15.*
diff --git a/sources/shiboken6/libshiboken/signature/signature_extend.cpp b/sources/shiboken6/libshiboken/signature/signature_extend.cpp
index 047b0e0e4..7292f8216 100644
--- a/sources/shiboken6/libshiboken/signature/signature_extend.cpp
+++ b/sources/shiboken6/libshiboken/signature/signature_extend.cpp
@@ -58,32 +58,26 @@ static PyObject *_get_written_signature(signaturefunc sf, PyObject *ob, PyObject
#ifdef PYPY_VERSION
PyObject *pyside_bm_get___signature__(PyObject *func, PyObject *modifier)
{
- init_module_2();
return _get_written_signature(GetSignature_Method, func, modifier);
}
#endif
PyObject *pyside_cf_get___signature__(PyObject *func, PyObject *modifier)
{
- init_module_2();
return _get_written_signature(GetSignature_Function, func, modifier);
}
PyObject *pyside_sm_get___signature__(PyObject *sm, PyObject *modifier)
{
- init_module_2();
AutoDecRef func(PyObject_GetAttr(sm, PyMagicName::func()));
- if (Py_TYPE(func) == PepFunction_TypePtr)
- return PyObject_GetAttr(func, PyMagicName::signature());
return _get_written_signature(GetSignature_Function, func, modifier);
}
PyObject *pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier)
{
- init_module_2();
AutoDecRef func(name_key_to_func(ob_md));
if (func.object() == Py_None)
- return Py_None;
+ Py_RETURN_NONE;
if (func.isNull())
Py_FatalError("missing mapping in MethodDescriptor");
return pyside_cf_get___signature__(func, modifier);
@@ -91,13 +85,11 @@ PyObject *pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier)
PyObject *pyside_wd_get___signature__(PyObject *ob, PyObject *modifier)
{
- init_module_2();
return _get_written_signature(GetSignature_Wrapper, ob, modifier);
}
PyObject *pyside_tp_get___signature__(PyObject *obtype_mod, PyObject *modifier)
{
- init_module_2();
return _get_written_signature(GetSignature_TypeMod, obtype_mod, modifier);
}
@@ -127,17 +119,17 @@ static int handle_doc_in_progress = 0;
static PyObject *handle_doc(PyObject *ob, PyObject *old_descr)
{
- init_module_1();
- init_module_2();
AutoDecRef ob_type_mod(GetClassOrModOf(ob));
const char *name;
- if (PyModule_Check(ob_type_mod.object()))
+ bool isModule = PyModule_Check(ob_type_mod.object());
+ if (isModule)
name = PyModule_GetName(ob_type_mod.object());
else
name = reinterpret_cast<PyTypeObject *>(ob_type_mod.object())->tp_name;
PyObject *res{};
- if (handle_doc_in_progress || name == nullptr || strncmp(name, "PySide6.", 8) != 0) {
+ if (handle_doc_in_progress || name == nullptr
+ || (isModule && strncmp(name, "PySide6.", 8) != 0)) {
res = PyObject_CallMethodObjArgs(old_descr, PyMagicName::get(), ob, nullptr);
} else {
handle_doc_in_progress++;
@@ -177,59 +169,29 @@ static PyObject *pyside_wd_get___doc__(PyObject *wd)
return handle_doc(wd, old_wd_doc_descr);
}
-// the default setter for all objects
-static int pyside_set___signature__(PyObject *op, PyObject *value)
-{
- // By this additional check, this function refuses write access.
- // We consider both nullptr and Py_None as not been written.
- AutoDecRef has_val(get_signature_intern(op, nullptr));
- if (!(has_val.isNull() || has_val == Py_None)) {
- PyErr_Format(PyExc_AttributeError,
- "Attribute '__signature__' of '%.50s' object is not writable",
- Py_TYPE(op)->tp_name);
- return -1;
- }
- int ret = value == nullptr ? PyDict_DelItem(pyside_globals->value_dict, op)
- : PyDict_SetItem(pyside_globals->value_dict, op, value);
- Py_XINCREF(value);
- return ret;
-}
-
// PYSIDE-535: We cannot patch types easily in PyPy.
// Let's use the `get_signature` function, instead.
static PyGetSetDef new_PyCFunction_getsets[] = {
{const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_cf_get___doc__),
nullptr, nullptr, nullptr},
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_cf_get___signature__),
- reinterpret_cast<setter>(pyside_set___signature__),
- nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}
};
static PyGetSetDef new_PyStaticMethod_getsets[] = {
{const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_sm_get___doc__),
nullptr, nullptr, nullptr},
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_sm_get___signature__),
- reinterpret_cast<setter>(pyside_set___signature__),
- nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}
};
static PyGetSetDef new_PyMethodDescr_getsets[] = {
{const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_md_get___doc__),
nullptr, nullptr, nullptr},
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_md_get___signature__),
- reinterpret_cast<setter>(pyside_set___signature__),
- nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}
};
static PyGetSetDef new_PyWrapperDescr_getsets[] = {
{const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_wd_get___doc__),
nullptr, nullptr, nullptr},
- {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_wd_get___signature__),
- reinterpret_cast<setter>(pyside_set___signature__),
- nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}
};
diff --git a/sources/shiboken6/libshiboken/signature/signature_globals.cpp b/sources/shiboken6/libshiboken/signature/signature_globals.cpp
index 71f3d36ae..3a79a12d5 100644
--- a/sources/shiboken6/libshiboken/signature/signature_globals.cpp
+++ b/sources/shiboken6/libshiboken/signature/signature_globals.cpp
@@ -28,26 +28,13 @@ static const unsigned char PySide_SignatureLoader[] = {
#include "embed/signature_bootstrap_inc.h"
};
-static PyObject *_init_pyside_extension(PyObject * /* self */, PyObject * /* args */)
+static safe_globals_struc *init_phase_1()
{
- init_module_1();
- init_module_2();
- Py_RETURN_NONE;
-}
-
-// This function will be inserted into __builtins__.
-static PyMethodDef init_methods[] = {
- {"_init_pyside_extension", (PyCFunction)_init_pyside_extension, METH_NOARGS},
- {nullptr, nullptr}
-};
-
-static safe_globals_struc *init_phase_1(PyMethodDef *init_meth)
-{
- {
+ do {
auto *p = reinterpret_cast<safe_globals_struc *>
(malloc(sizeof(safe_globals_struc)));
if (p == nullptr)
- goto error;
+ break;
/*
* Initializing module signature_bootstrap.
* Since we now have an embedding script, we can do this without any
@@ -57,23 +44,21 @@ static safe_globals_struc *init_phase_1(PyMethodDef *init_meth)
// We must work for multiple versions or we are cross-building for a different
// Python version interpreter, so use source code.
#else
- AutoDecRef marshal_module(PyImport_Import(PyName::marshal()));
- if (marshal_module.isNull())
- goto error;
+ AutoDecRef marshal_module(PyImport_Import(PyName::marshal())); // builtin
AutoDecRef loads(PyObject_GetAttr(marshal_module, PyName::loads()));
if (loads.isNull())
- goto error;
+ break;
#endif
char *bytes_cast = reinterpret_cast<char *>(
const_cast<unsigned char *>(PySide_SignatureLoader));
AutoDecRef bytes(PyBytes_FromStringAndSize(bytes_cast, sizeof(PySide_SignatureLoader)));
if (bytes.isNull())
- goto error;
+ break;
#if defined(Py_LIMITED_API) || defined(SHIBOKEN_NO_EMBEDDING_PYC)
PyObject *builtins = PyEval_GetBuiltins();
PyObject *compile = PyDict_GetItem(builtins, PyName::compile());
if (compile == nullptr)
- goto error;
+ break;
AutoDecRef code_obj(PyObject_CallFunction(compile, "Oss",
bytes.object(), "signature_bootstrap.py", "exec"));
#else
@@ -81,69 +66,62 @@ static safe_globals_struc *init_phase_1(PyMethodDef *init_meth)
loads, bytes.object(), nullptr));
#endif
if (code_obj.isNull())
- goto error;
+ break;
p->helper_module = PyImport_ExecCodeModule("signature_bootstrap", code_obj);
if (p->helper_module == nullptr)
- goto error;
+ break;
// Initialize the module
PyObject *mdict = PyModule_GetDict(p->helper_module);
if (PyDict_SetItem(mdict, PyMagicName::builtins(), PyEval_GetBuiltins()) < 0)
- goto error;
- /*
- * Unpack an embedded ZIP file with more signature modules.
+ break;
+
+ /*********************************************************************
+ *
+ * Attention!
+ * ----------
+ *
+ * We are unpacking an embedded ZIP file with more signature modules.
* They will be loaded later with the zipimporter.
- * Due to MSVC's limitation to 64k strings, we need to assemble pieces.
+ * The file `signature_bootstrap.py` does the unpacking and starts the
+ * loader. See `init_phase_2`.
+ *
+ * Due to MSVC's limitation to 64k strings, we needed to assemble pieces.
*/
auto **block_ptr = reinterpret_cast<const char **>(PySide_CompressedSignaturePackage);
- int npieces = 0;
- PyObject *piece, *zipped_string_sequence = PyList_New(0);
- if (zipped_string_sequence == nullptr)
- return nullptr;
+ PyObject *piece{};
+ AutoDecRef zipped_string_sequence(PyList_New(0));
for (; **block_ptr != 0; ++block_ptr) {
- npieces++;
// we avoid the string/unicode dilemma by not using PyString_XXX:
piece = Py_BuildValue("s", *block_ptr);
if (piece == nullptr || PyList_Append(zipped_string_sequence, piece) < 0)
- goto error;
+ break;
}
if (PyDict_SetItemString(mdict, "zipstring_sequence", zipped_string_sequence) < 0)
- goto error;
- Py_DECREF(zipped_string_sequence);
+ break;
// build a dict for diverse mappings
p->map_dict = PyDict_New();
- if (p->map_dict == nullptr)
- goto error;
// build a dict for the prepared arguments
p->arg_dict = PyDict_New();
- if (p->arg_dict == nullptr
- || PyObject_SetAttrString(p->helper_module, "pyside_arg_dict", p->arg_dict) < 0)
- goto error;
+ if (PyObject_SetAttrString(p->helper_module, "pyside_arg_dict", p->arg_dict) < 0)
+ break;
// build a dict for assigned signature values
p->value_dict = PyDict_New();
- if (p->value_dict == nullptr)
- goto error;
// PYSIDE-1019: build a __feature__ dict
p->feature_dict = PyDict_New();
- if (p->feature_dict == nullptr
- || PyObject_SetAttrString(p->helper_module, "pyside_feature_dict", p->feature_dict) < 0)
- goto error;
+ if (PyObject_SetAttrString(p->helper_module, "pyside_feature_dict", p->feature_dict) < 0)
+ break;
// This function will be disabled until phase 2 is done.
p->finish_import_func = nullptr;
- // Initialize the explicit init function.
- AutoDecRef init(PyCFunction_NewEx(init_meth, nullptr, nullptr));
- if (init.isNull()
- || PyDict_SetItemString(PyEval_GetBuiltins(), init_meth->ml_name, init) != 0)
- goto error;
-
return p;
- }
-error:
+
+ } while (0);
+
PyErr_Print();
Py_FatalError("could not initialize part 1");
return nullptr;
@@ -151,7 +129,7 @@ error:
static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods)
{
- {
+ do {
PyMethodDef *ml;
// The single function to be called, but maybe more to come.
@@ -159,7 +137,7 @@ static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods)
PyObject *v = PyCFunction_NewEx(ml, nullptr, nullptr);
if (v == nullptr
|| PyObject_SetAttrString(p->helper_module, ml->ml_name, v) != 0)
- goto error;
+ break;
Py_DECREF(v);
}
// The first entry is __feature_import__, add documentation.
@@ -170,33 +148,59 @@ static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods)
PyObject *bootstrap_func = PyObject_GetAttrString(p->helper_module, "bootstrap");
if (bootstrap_func == nullptr)
- goto error;
- // The return value of the bootstrap function is the loader module.
- PyObject *loader = PyObject_CallFunction(bootstrap_func, "()");
+ break;
+
+ /*********************************************************************
+ *
+ * Attention!
+ * ----------
+ *
+ * This is the entry point where everything in folder
+ * `shibokensupport` becomes initialized. It starts with
+ * `signature_bootstrap.py` and continues from there to `loader.py`.
+ *
+ * The return value of the bootstrap function is the loader module.
+ */
+ PyObject *loader = PyObject_CallFunctionObjArgs(bootstrap_func, nullptr);
if (loader == nullptr)
- goto error;
+ break;
+
// now the loader should be initialized
p->pyside_type_init_func = PyObject_GetAttrString(loader, "pyside_type_init");
if (p->pyside_type_init_func == nullptr)
- goto error;
+ break;
p->create_signature_func = PyObject_GetAttrString(loader, "create_signature");
if (p->create_signature_func == nullptr)
- goto error;
+ break;
p->seterror_argument_func = PyObject_GetAttrString(loader, "seterror_argument");
if (p->seterror_argument_func == nullptr)
- goto error;
+ break;
p->make_helptext_func = PyObject_GetAttrString(loader, "make_helptext");
if (p->make_helptext_func == nullptr)
- goto error;
+ break;
p->finish_import_func = PyObject_GetAttrString(loader, "finish_import");
if (p->finish_import_func == nullptr)
- goto error;
+ break;
p->feature_import_func = PyObject_GetAttrString(loader, "feature_import");
if (p->feature_import_func == nullptr)
- goto error;
+ break;
+ p->feature_imported_func = PyObject_GetAttrString(loader, "feature_imported");
+ if (p->feature_imported_func == nullptr)
+ break;
+
+ // We call stuff like the feature initialization late,
+ // after all the function pointers are in place.
+ PyObject *post_init_func = PyObject_GetAttrString(loader, "post_init");
+ if (post_init_func == nullptr)
+ break;
+ PyObject *ret = PyObject_CallFunctionObjArgs(post_init_func, nullptr);
+ if (ret == nullptr)
+ break;
+
return 0;
- }
-error:
+
+ } while (0);
+
PyErr_Print();
Py_FatalError("could not initialize part 2");
return -1;
@@ -205,12 +209,12 @@ error:
#ifndef _WIN32
////////////////////////////////////////////////////////////////////////////
// a stack trace for linux-like platforms
-#include <stdio.h>
+#include <cstdio>
#if defined(__GLIBC__)
# include <execinfo.h>
#endif
#include <signal.h>
-#include <stdlib.h>
+#include <cstdlib>
#include <unistd.h>
static void handler(int sig) {
@@ -223,7 +227,7 @@ static void handler(int sig) {
// print out all the frames to stderr
#endif
- fprintf(stderr, "Error: signal %d:\n", sig);
+ std::fprintf(stderr, "Error: signal %d:\n", sig);
#if defined(__GLIBC__)
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
@@ -233,14 +237,14 @@ static void handler(int sig) {
////////////////////////////////////////////////////////////////////////////
#endif // _WIN32
-safe_globals pyside_globals = nullptr;
+safe_globals_struc *pyside_globals = nullptr;
-void init_module_1(void)
+void init_shibokensupport_module(void)
{
static int init_done = 0;
if (!init_done) {
- pyside_globals = init_phase_1(init_methods);
+ pyside_globals = init_phase_1();
if (pyside_globals != nullptr)
init_done = 1;
@@ -251,17 +255,6 @@ void init_module_1(void)
signal(SIGSEGV, handler); // install our handler
#endif // _WIN32
- }
-}
-
-void init_module_2(void)
-{
- static int init_done = 0;
-
- if (!init_done) {
- // Phase 2 will call __init__.py which touches a signature, itself.
- // Therefore we set init_done prior to init_phase_2().
- init_done = 1;
init_phase_2(pyside_globals, signature_methods);
// Enum must be initialized when signatures exist, not earlier.
init_enum();
diff --git a/sources/shiboken6/libshiboken/signature/signature_helper.cpp b/sources/shiboken6/libshiboken/signature/signature_helper.cpp
index ef0c021d5..cf84cfa13 100644
--- a/sources/shiboken6/libshiboken/signature/signature_helper.cpp
+++ b/sources/shiboken6/libshiboken/signature/signature_helper.cpp
@@ -51,10 +51,13 @@ int add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr)
/*
* This function is used to assign a new `__signature__` attribute,
* and also to override a `__doc__` or `__name__` attribute.
+ *
+ * PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter.
*/
assert(PyType_Check(type));
PyType_Ready(type);
- PyObject *dict = type->tp_dict;
+ AutoDecRef tpDict(PepType_GetDict(type));
+ auto *dict = tpDict.object();
for (; gsp->name != nullptr; gsp++) {
PyObject *have_descr = PyDict_GetItemString(dict, gsp->name);
if (have_descr != nullptr) {
@@ -291,7 +294,7 @@ PyObject *_address_to_stringlist(PyObject *numkey)
return res_list;
}
-static int _build_func_to_type(PyObject *obtype)
+int _build_func_to_type(PyObject *obtype)
{
/*
* There is no general way to directly get the type of a static method.
@@ -307,7 +310,17 @@ static int _build_func_to_type(PyObject *obtype)
* We also check for hidden methods, see below.
*/
auto *type = reinterpret_cast<PyTypeObject *>(obtype);
- PyObject *dict = type->tp_dict;
+ AutoDecRef tpDict(PepType_GetDict(type));
+ auto *dict = tpDict.object();
+
+ // PYSIDE-2404: Get the original dict for late initialization.
+ // The dict might have been switched before signature init.
+ static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type);
+ if (Py_TYPE(dict) != Py_TYPE(pyTypeType_tp_dict)) {
+ tpDict.reset(PyObject_GetAttr(dict, PyName::orig_dict()));
+ dict = tpDict.object();
+ }
+
PyMethodDef *meth = type->tp_methods;
if (meth == nullptr)
@@ -373,26 +386,4 @@ static int _build_func_to_type(PyObject *obtype)
return 0;
}
-int _finish_nested_classes(PyObject *obdict)
-{
- PyObject *key, *value, *obtype;
- PyTypeObject *subtype;
- Py_ssize_t pos = 0;
-
- if (obdict == nullptr)
- return -1;
- while (PyDict_Next(obdict, &pos, &key, &value)) {
- if (PyType_Check(value)) {
- obtype = value;
- if (_build_func_to_type(obtype) < 0)
- return -1;
- // now continue with nested cases
- subtype = reinterpret_cast<PyTypeObject *>(obtype);
- if (_finish_nested_classes(subtype->tp_dict) < 0)
- return -1;
- }
- }
- return 0;
-}
-
} // extern "C"
diff --git a/sources/shiboken6/libshiboken/signature_p.h b/sources/shiboken6/libshiboken/signature_p.h
index 99e339ce2..d0c4ee537 100644
--- a/sources/shiboken6/libshiboken/signature_p.h
+++ b/sources/shiboken6/libshiboken/signature_p.h
@@ -10,7 +10,7 @@ extern "C" {
// signature_globals.cpp
-typedef struct safe_globals_struc {
+struct safe_globals_struc {
// init part 1: get arg_dict
PyObject *helper_module;
PyObject *arg_dict;
@@ -24,13 +24,13 @@ typedef struct safe_globals_struc {
PyObject *make_helptext_func;
PyObject *finish_import_func;
PyObject *feature_import_func;
-} safe_globals_struc, *safe_globals;
+ PyObject *feature_imported_func;
+};
-extern safe_globals pyside_globals;
+extern safe_globals_struc *pyside_globals;
extern PyMethodDef signature_methods[];
-void init_module_1(void);
-void init_module_2(void);
+void init_shibokensupport_module(void);
// signature.cpp
@@ -63,6 +63,7 @@ PyObject *_get_class_of_cf(PyObject *ob_cf);
PyObject *_get_class_of_sm(PyObject *ob_sm);
PyObject *_get_class_of_descr(PyObject *ob);
PyObject *_address_to_stringlist(PyObject *numkey);
+int _build_func_to_type(PyObject *obtype);
int _finish_nested_classes(PyObject *dict);
#ifdef PYPY_VERSION
diff --git a/sources/shiboken6/libshiboken/voidptr.cpp b/sources/shiboken6/libshiboken/voidptr.cpp
index c047a8b7c..8bb3f6ac8 100644
--- a/sources/shiboken6/libshiboken/voidptr.cpp
+++ b/sources/shiboken6/libshiboken/voidptr.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "voidptr.h"
+#include "pep384ext.h"
#include "sbkconverter.h"
#include "basewrapper.h"
#include "basewrapper_p.h"
@@ -10,22 +11,21 @@ extern "C"
{
// Void pointer object definition.
-typedef struct {
+struct SbkVoidPtrObject {
PyObject_HEAD
void *cptr;
Py_ssize_t size;
bool isWritable;
-} SbkVoidPtrObject;
+};
-PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject * /* args */, PyObject * /* kwds */)
{
// PYSIDE-560: It is much safer to first call a function and then do a
// type cast than to do everything in one line. The bad construct looked
// like this, actual call forgotten:
// SbkVoidPtrObject *self =
// reinterpret_cast<SbkVoidPtrObject *>(type->tp_alloc);
- PyObject *ob = type->tp_alloc(type, 0);
- auto *self = reinterpret_cast<SbkVoidPtrObject *>(ob);
+ auto *self = PepExt_TypeCallAlloc<SbkVoidPtrObject>(type, 0);
if (self != nullptr) {
self->cptr = nullptr;
@@ -153,13 +153,12 @@ PyObject *SbkVoidPtrObject_int(PyObject *v)
return PyLong_FromVoidPtr(sbkObject->cptr);
}
-PyObject *toBytes(PyObject *self, PyObject *args)
+PyObject *toBytes(PyObject *self, PyObject * /* args */)
{
auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self);
- if (sbkObject->size < 0) {
- PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set.");
- return nullptr;
- }
+ if (sbkObject->size < 0)
+ return PyErr_Format(PyExc_IndexError, "VoidPtr does not have a size set.");
+
PyObject *bytes = PyBytes_FromStringAndSize(reinterpret_cast<const char *>(sbkObject->cptr),
sbkObject->size);
Py_XINCREF(bytes);
@@ -167,8 +166,8 @@ PyObject *toBytes(PyObject *self, PyObject *args)
}
static struct PyMethodDef SbkVoidPtrObject_methods[] = {
- {"toBytes", toBytes, METH_NOARGS},
- {nullptr}
+ {"toBytes", toBytes, METH_NOARGS, nullptr},
+ {nullptr, nullptr, 0, nullptr}
};
static Py_ssize_t SbkVoidPtrObject_length(PyObject *v)
@@ -256,38 +255,42 @@ static PyBufferProcs SbkVoidPtrObjectBufferProc = {
(releasebufferproc)nullptr // bf_releasebuffer
};
-// Void pointer type definition.
-static PyType_Slot SbkVoidPtrType_slots[] = {
- {Py_tp_repr, reinterpret_cast<void *>(SbkVoidPtrObject_repr)},
- {Py_nb_int, reinterpret_cast<void *>(SbkVoidPtrObject_int)},
- {Py_sq_length, reinterpret_cast<void *>(SbkVoidPtrObject_length)},
- {Py_tp_str, reinterpret_cast<void *>(SbkVoidPtrObject_str)},
- {Py_tp_richcompare, reinterpret_cast<void *>(SbkVoidPtrObject_richcmp)},
- {Py_tp_init, reinterpret_cast<void *>(SbkVoidPtrObject_init)},
- {Py_tp_new, reinterpret_cast<void *>(SbkVoidPtrObject_new)},
- {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)},
- {Py_tp_methods, reinterpret_cast<void *>(SbkVoidPtrObject_methods)},
- {0, nullptr}
-};
-static PyType_Spec SbkVoidPtrType_spec = {
- "2:shiboken6.Shiboken.VoidPtr",
- sizeof(SbkVoidPtrObject),
- 0,
- Py_TPFLAGS_DEFAULT,
- SbkVoidPtrType_slots,
-};
-
-
+static PyTypeObject *createVoidPtrType()
+{
+ PyType_Slot SbkVoidPtrType_slots[] = {
+ {Py_tp_repr, reinterpret_cast<void *>(SbkVoidPtrObject_repr)},
+ {Py_nb_int, reinterpret_cast<void *>(SbkVoidPtrObject_int)},
+ {Py_sq_length, reinterpret_cast<void *>(SbkVoidPtrObject_length)},
+ {Py_tp_str, reinterpret_cast<void *>(SbkVoidPtrObject_str)},
+ {Py_tp_richcompare, reinterpret_cast<void *>(SbkVoidPtrObject_richcmp)},
+ {Py_tp_init, reinterpret_cast<void *>(SbkVoidPtrObject_init)},
+ {Py_tp_new, reinterpret_cast<void *>(SbkVoidPtrObject_new)},
+ {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)},
+ {Py_tp_methods, reinterpret_cast<void *>(SbkVoidPtrObject_methods)},
+ {0, nullptr}
+ };
+
+ PyType_Spec SbkVoidPtrType_spec = {
+ "2:shiboken6.Shiboken.VoidPtr",
+ sizeof(SbkVoidPtrObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ SbkVoidPtrType_slots,
+ };
+
+ return SbkType_FromSpec_BMDWB(&SbkVoidPtrType_spec,
+ nullptr, nullptr, 0, 0,
+ &SbkVoidPtrObjectBufferProc);
}
PyTypeObject *SbkVoidPtr_TypeF(void)
{
- static PyTypeObject *type = SbkType_FromSpec_BMDWB(&SbkVoidPtrType_spec,
- nullptr, nullptr, 0, 0,
- &SbkVoidPtrObjectBufferProc);
+ static auto *type = createVoidPtrType();
return type;
}
+} // extern "C"
+
namespace VoidPtr {
static int voidPointerInitialized = false;
diff --git a/sources/shiboken6/shibokenmodule/CMakeLists.txt b/sources/shiboken6/shibokenmodule/CMakeLists.txt
index cd0dc176d..702750450 100644
--- a/sources/shiboken6/shibokenmodule/CMakeLists.txt
+++ b/sources/shiboken6/shibokenmodule/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(shibokenmodule)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shibokenmodule.txt.in"
@@ -7,25 +10,30 @@ set(sample_SRC ${CMAKE_CURRENT_BINARY_DIR}/Shiboken/shiboken_module_wrapper.cpp)
set(shibokenmodule_TYPESYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_shiboken.xml)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
add_custom_command(
-OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
-BYPRODUCTS ${sample_SRC}
-# Note: shiboken6 is an executable target. By not specifying its explicit
-# path, CMAKE figures it out, itself!
-# This fixes an issue with Visual Studio, see https://github.com/PySide/shiboken6/pull/11
-COMMAND Shiboken6::shiboken6
- --project-file=${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt ${GENERATOR_EXTRA_FLAGS}
-DEPENDS ${shibokenmodule_TYPESYSTEM}
-WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-COMMENT "Running generator for 'Shiboken'..."
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${sample_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --project-file=${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt
+ ${GENERATOR_EXTRA_FLAGS}
+ DEPENDS ${shibokenmodule_TYPESYSTEM}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for 'Shiboken'..."
)
add_library(shibokenmodule MODULE ${sample_SRC})
target_include_directories(shibokenmodule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR})
-set_property(TARGET shibokenmodule PROPERTY PREFIX "")
-# PYSIDE-1497: This `..` is the crucial trick to unify the path location of `Shiboken`.
-set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "../Shiboken${PYTHON_EXTENSION_SUFFIX}")
+
+set_target_properties(shibokenmodule PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "Shiboken${PYTHON_EXTENSION_SUFFIX}"
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/..")
if(WIN32)
set_property(TARGET shibokenmodule PROPERTY SUFFIX ".pyd")
diff --git a/sources/shiboken6/shibokenmodule/Shiboken.pyi b/sources/shiboken6/shibokenmodule/Shiboken.pyi
index a6feeae15..6a1a63217 100644
--- a/sources/shiboken6/shibokenmodule/Shiboken.pyi
+++ b/sources/shiboken6/shibokenmodule/Shiboken.pyi
@@ -18,19 +18,20 @@ class Object(object):
def __init__(self) -> None: ...
-class VoidPtr(object): ...
+class VoidPtr(object):
+ def __init__(self, value: int) -> None: ...
def _unpickle_enum(arg__1: object, arg__2: object) -> object: ...
-def createdByPython(arg__1: object) -> bool: ...
-def delete(arg__1: object) -> None: ...
-def dump(arg__1: object) -> object: ...
-def getAllValidWrappers() -> object: ...
-def getCppPointer(arg__1: object) -> object: ...
-def invalidate(arg__1: object) -> None: ...
+def createdByPython(arg__1: Shiboken.Object) -> bool: ...
+def delete(arg__1: Shiboken.Object) -> None: ...
+def dump(arg__1: object) -> str: ...
+def getAllValidWrappers() -> list[Shiboken.Object]: ...
+def getCppPointer(arg__1: Shiboken.Object) -> tuple[int, ...]: ...
+def invalidate(arg__1: Shiboken.Object) -> None: ...
def isValid(arg__1: object) -> bool: ...
-def ownedByPython(arg__1: object) -> bool: ...
-def wrapInstance(arg__1: int, arg__2: type) -> object: ...
+def ownedByPython(arg__1: Shiboken.Object) -> bool: ...
+def wrapInstance(arg__1: int, arg__2: type) -> Shiboken.Object: ...
# eof
diff --git a/sources/shiboken6/shibokenmodule/__init__.py.in b/sources/shiboken6/shibokenmodule/__init__.py.in
index 5508403a9..c859160bc 100644
--- a/sources/shiboken6/shibokenmodule/__init__.py.in
+++ b/sources/shiboken6/shibokenmodule/__init__.py.in
@@ -25,6 +25,3 @@ import functools
import typing
from shiboken6.Shiboken import *
-
-# Trigger signature initialization via __builtins__.
-_init_pyside_extension()
diff --git a/sources/shiboken6/shibokenmodule/_config.py.in b/sources/shiboken6/shibokenmodule/_config.py.in
index 92b3cd23c..600c431c9 100644
--- a/sources/shiboken6/shibokenmodule/_config.py.in
+++ b/sources/shiboken6/shibokenmodule/_config.py.in
@@ -9,3 +9,4 @@ version_info = (@shiboken_MAJOR_VERSION@, @shiboken_MINOR_VERSION@, @shiboken_MI
@PACKAGE_BUILD_COMMIT_HASH_DESCRIBED@
@PACKAGE_SETUP_PY_PACKAGE_TIMESTAMP_ASSIGNMENT@
@PACKAGE_SETUP_PY_PACKAGE_VERSION_ASSIGNMENT@
+@QT_MACOS_DEPLOYMENT_TARGET@
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py
deleted file mode 100644
index b6430c89a..000000000
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py
+++ /dev/null
@@ -1,1102 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-PSF_LICENSE = """
-PSF LICENSE AGREEMENT FOR PYTHON 3.10.4
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 3.10.4 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 3.10.4 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2022 Python Software Foundation; All Rights
- Reserved" are retained in Python 3.10.4 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 3.10.4 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 3.10.4.
-
-4. PSF is making Python 3.10.4 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 3.10.4 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.10.4
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.10.4, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 3.10.4, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
-"""
-
-import sys
-from types import MappingProxyType, DynamicClassAttribute
-
-
-__all__ = [
- 'EnumMeta',
- 'Enum', 'IntEnum', 'Flag', 'IntFlag',
- 'auto', 'unique',
- ]
-
-
-def _is_descriptor(obj):
- """
- Returns True if obj is a descriptor, False otherwise.
- """
- return (
- hasattr(obj, '__get__') or
- hasattr(obj, '__set__') or
- hasattr(obj, '__delete__')
- )
-
-def _is_dunder(name):
- """
- Returns True if a __dunder__ name, False otherwise.
- """
- return (
- len(name) > 4 and
- name[:2] == name[-2:] == '__' and
- name[2] != '_' and
- name[-3] != '_'
- )
-
-def _is_sunder(name):
- """
- Returns True if a _sunder_ name, False otherwise.
- """
- return (
- len(name) > 2 and
- name[0] == name[-1] == '_' and
- name[1:2] != '_' and
- name[-2:-1] != '_'
- )
-
-def _is_private(cls_name, name):
- # do not use `re` as `re` imports `enum`
- pattern = '_%s__' % (cls_name, )
- pat_len = len(pattern)
- if (
- len(name) > pat_len
- and name.startswith(pattern)
- and name[pat_len:pat_len+1] != ['_']
- and (name[-1] != '_' or name[-2] != '_')
- ):
- return True
- else:
- return False
-
-def _make_class_unpicklable(cls):
- """
- Make the given class un-picklable.
- """
- def _break_on_call_reduce(self, proto):
- raise TypeError('%r cannot be pickled' % self)
- cls.__reduce_ex__ = _break_on_call_reduce
- cls.__module__ = '<unknown>'
-
-_auto_null = object()
-class auto:
- """
- Instances are replaced with an appropriate value in Enum class suites.
- """
- value = _auto_null
-
-
-class _EnumDict(dict):
- """
- Track enum member order and ensure member names are not reused.
-
- EnumMeta will use the names found in self._member_names as the
- enumeration member names.
- """
- def __init__(self):
- super().__init__()
- self._member_names = []
- self._last_values = []
- self._ignore = []
- self._auto_called = False
-
- def __setitem__(self, key, value):
- """
- Changes anything not dundered or not a descriptor.
-
- If an enum member name is used twice, an error is raised; duplicate
- values are not checked for.
-
- Single underscore (sunder) names are reserved.
- """
- if _is_private(self._cls_name, key):
- import warnings
- warnings.warn(
- "private variables, such as %r, will be normal attributes in 3.11"
- % (key, ),
- DeprecationWarning,
- stacklevel=2,
- )
- if _is_sunder(key):
- if key not in (
- '_order_', '_create_pseudo_member_',
- '_generate_next_value_', '_missing_', '_ignore_',
- ):
- raise ValueError('_names_ are reserved for future Enum use')
- if key == '_generate_next_value_':
- # check if members already defined as auto()
- if self._auto_called:
- raise TypeError("_generate_next_value_ must be defined before members")
- setattr(self, '_generate_next_value', value)
- elif key == '_ignore_':
- if isinstance(value, str):
- value = value.replace(',',' ').split()
- else:
- value = list(value)
- self._ignore = value
- already = set(value) & set(self._member_names)
- if already:
- raise ValueError(
- '_ignore_ cannot specify already set names: %r'
- % (already, )
- )
- elif _is_dunder(key):
- if key == '__order__':
- key = '_order_'
- elif key in self._member_names:
- # descriptor overwriting an enum?
- raise TypeError('Attempted to reuse key: %r' % key)
- elif key in self._ignore:
- pass
- elif not _is_descriptor(value):
- if key in self:
- # enum overwriting a descriptor?
- raise TypeError('%r already defined as: %r' % (key, self[key]))
- if isinstance(value, auto):
- if value.value == _auto_null:
- value.value = self._generate_next_value(
- key,
- 1,
- len(self._member_names),
- self._last_values[:],
- )
- self._auto_called = True
- value = value.value
- self._member_names.append(key)
- self._last_values.append(value)
- super().__setitem__(key, value)
-
-
-# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
-# until EnumMeta finishes running the first time the Enum class doesn't exist.
-# This is also why there are checks in EnumMeta like `if Enum is not None`
-Enum = None
-
-class EnumMeta(type):
- """
- Metaclass for Enum
- """
- @classmethod
- def __prepare__(metacls, cls, bases, **kwds):
- # check that previous enum members do not exist
- metacls._check_for_existing_members(cls, bases)
- # create the namespace dict
- enum_dict = _EnumDict()
- enum_dict._cls_name = cls
- # inherit previous flags and _generate_next_value_ function
- member_type, first_enum = metacls._get_mixins_(cls, bases)
- if first_enum is not None:
- enum_dict['_generate_next_value_'] = getattr(
- first_enum, '_generate_next_value_', None,
- )
- return enum_dict
-
- def __new__(metacls, cls, bases, classdict, **kwds):
- # an Enum class is final once enumeration items have been defined; it
- # cannot be mixed with other types (int, float, etc.) if it has an
- # inherited __new__ unless a new __new__ is defined (or the resulting
- # class will fail).
- #
- # remove any keys listed in _ignore_
- classdict.setdefault('_ignore_', []).append('_ignore_')
- ignore = classdict['_ignore_']
- for key in ignore:
- classdict.pop(key, None)
- member_type, first_enum = metacls._get_mixins_(cls, bases)
- __new__, save_new, use_args = metacls._find_new_(
- classdict, member_type, first_enum,
- )
-
- # save enum items into separate mapping so they don't get baked into
- # the new class
- enum_members = {k: classdict[k] for k in classdict._member_names}
- for name in classdict._member_names:
- del classdict[name]
-
- # adjust the sunders
- _order_ = classdict.pop('_order_', None)
-
- # check for illegal enum names (any others?)
- invalid_names = set(enum_members) & {'mro', ''}
- if invalid_names:
- raise ValueError('Invalid enum member name: {0}'.format(
- ','.join(invalid_names)))
-
- # create a default docstring if one has not been provided
- if '__doc__' not in classdict:
- classdict['__doc__'] = 'An enumeration.'
-
- enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
- enum_class._member_names_ = [] # names in definition order
- enum_class._member_map_ = {} # name->value map
- enum_class._member_type_ = member_type
-
- # save DynamicClassAttribute attributes from super classes so we know
- # if we can take the shortcut of storing members in the class dict
- dynamic_attributes = {
- k for c in enum_class.mro()
- for k, v in c.__dict__.items()
- if isinstance(v, DynamicClassAttribute)
- }
-
- # Reverse value->name map for hashable values.
- enum_class._value2member_map_ = {}
-
- # If a custom type is mixed into the Enum, and it does not know how
- # to pickle itself, pickle.dumps will succeed but pickle.loads will
- # fail. Rather than have the error show up later and possibly far
- # from the source, sabotage the pickle protocol for this class so
- # that pickle.dumps also fails.
- #
- # However, if the new class implements its own __reduce_ex__, do not
- # sabotage -- it's on them to make sure it works correctly. We use
- # __reduce_ex__ instead of any of the others as it is preferred by
- # pickle over __reduce__, and it handles all pickle protocols.
- if '__reduce_ex__' not in classdict:
- if member_type is not object:
- methods = ('__getnewargs_ex__', '__getnewargs__',
- '__reduce_ex__', '__reduce__')
- if not any(m in member_type.__dict__ for m in methods):
- if '__new__' in classdict:
- # too late, sabotage
- _make_class_unpicklable(enum_class)
- else:
- # final attempt to verify that pickling would work:
- # travel mro until __new__ is found, checking for
- # __reduce__ and friends along the way -- if any of them
- # are found before/when __new__ is found, pickling should
- # work
- sabotage = None
- for chain in bases:
- for base in chain.__mro__:
- if base is object:
- continue
- elif any(m in base.__dict__ for m in methods):
- # found one, we're good
- sabotage = False
- break
- elif '__new__' in base.__dict__:
- # not good
- sabotage = True
- break
- if sabotage is not None:
- break
- if sabotage:
- _make_class_unpicklable(enum_class)
- # instantiate them, checking for duplicates as we go
- # we instantiate first instead of checking for duplicates first in case
- # a custom __new__ is doing something funky with the values -- such as
- # auto-numbering ;)
- for member_name in classdict._member_names:
- value = enum_members[member_name]
- if not isinstance(value, tuple):
- args = (value, )
- else:
- args = value
- if member_type is tuple: # special case for tuple enums
- args = (args, ) # wrap it one more time
- if not use_args:
- enum_member = __new__(enum_class)
- if not hasattr(enum_member, '_value_'):
- enum_member._value_ = value
- else:
- enum_member = __new__(enum_class, *args)
- if not hasattr(enum_member, '_value_'):
- if member_type is object:
- enum_member._value_ = value
- else:
- enum_member._value_ = member_type(*args)
- value = enum_member._value_
- enum_member._name_ = member_name
- enum_member.__objclass__ = enum_class
- enum_member.__init__(*args)
- # If another member with the same value was already defined, the
- # new member becomes an alias to the existing one.
- for name, canonical_member in enum_class._member_map_.items():
- if canonical_member._value_ == enum_member._value_:
- enum_member = canonical_member
- break
- else:
- # Aliases don't appear in member names (only in __members__).
- enum_class._member_names_.append(member_name)
- # performance boost for any member that would not shadow
- # a DynamicClassAttribute
- if member_name not in dynamic_attributes:
- setattr(enum_class, member_name, enum_member)
- # now add to _member_map_
- enum_class._member_map_[member_name] = enum_member
- try:
- # This may fail if value is not hashable. We can't add the value
- # to the map, and by-value lookups for this value will be
- # linear.
- enum_class._value2member_map_[value] = enum_member
- except TypeError:
- pass
-
- # double check that repr and friends are not the mixin's or various
- # things break (such as pickle)
- # however, if the method is defined in the Enum itself, don't replace
- # it
- for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
- if name in classdict:
- continue
- class_method = getattr(enum_class, name)
- obj_method = getattr(member_type, name, None)
- enum_method = getattr(first_enum, name, None)
- if obj_method is not None and obj_method is class_method:
- setattr(enum_class, name, enum_method)
-
- # replace any other __new__ with our own (as long as Enum is not None,
- # anyway) -- again, this is to support pickle
- if Enum is not None:
- # if the user defined their own __new__, save it before it gets
- # clobbered in case they subclass later
- if save_new:
- enum_class.__new_member__ = __new__
- enum_class.__new__ = Enum.__new__
-
- # py3 support for definition order (helps keep py2/py3 code in sync)
- if _order_ is not None:
- if isinstance(_order_, str):
- _order_ = _order_.replace(',', ' ').split()
- if _order_ != enum_class._member_names_:
- raise TypeError('member order does not match _order_')
-
- return enum_class
-
- def __bool__(self):
- """
- classes/types should always be True.
- """
- return True
-
- def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
- """
- Either returns an existing member, or creates a new enum class.
-
- This method is used both when an enum class is given a value to match
- to an enumeration member (i.e. Color(3)) and for the functional API
- (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
-
- When used for the functional API:
-
- `value` will be the name of the new class.
-
- `names` should be either a string of white-space/comma delimited names
- (values will start at `start`), or an iterator/mapping of name, value pairs.
-
- `module` should be set to the module this class is being created in;
- if it is not set, an attempt to find that module will be made, but if
- it fails the class will not be picklable.
-
- `qualname` should be set to the actual location this class can be found
- at in its module; by default it is set to the global scope. If this is
- not correct, unpickling will fail in some circumstances.
-
- `type`, if set, will be mixed in as the first base class.
- """
- if names is None: # simple value lookup
- return cls.__new__(cls, value)
- # otherwise, functional API: we're creating a new Enum type
- return cls._create_(
- value,
- names,
- module=module,
- qualname=qualname,
- type=type,
- start=start,
- )
-
- def __contains__(cls, obj):
- if not isinstance(obj, Enum):
- import warnings
- warnings.warn(
- "in 3.12 __contains__ will no longer raise TypeError, but will return True if\n"
- "obj is a member or a member's value",
- DeprecationWarning,
- stacklevel=2,
- )
- raise TypeError(
- "unsupported operand type(s) for 'in': '%s' and '%s'" % (
- type(obj).__qualname__, cls.__class__.__qualname__))
- return isinstance(obj, cls) and obj._name_ in cls._member_map_
-
- def __delattr__(cls, attr):
- # nicer error message when someone tries to delete an attribute
- # (see issue19025).
- if attr in cls._member_map_:
- raise AttributeError("%s: cannot delete Enum member." % cls.__name__)
- super().__delattr__(attr)
-
- def __dir__(self):
- return (
- ['__class__', '__doc__', '__members__', '__module__']
- + self._member_names_
- )
-
- def __getattr__(cls, name):
- """
- Return the enum member matching `name`
-
- We use __getattr__ instead of descriptors or inserting into the enum
- class' __dict__ in order to support `name` and `value` being both
- properties for enum members (which live in the class' __dict__) and
- enum members themselves.
- """
- if _is_dunder(name):
- raise AttributeError(name)
- try:
- return cls._member_map_[name]
- except KeyError:
- raise AttributeError(name) from None
-
- def __getitem__(cls, name):
- return cls._member_map_[name]
-
- def __iter__(cls):
- """
- Returns members in definition order.
- """
- return (cls._member_map_[name] for name in cls._member_names_)
-
- def __len__(cls):
- return len(cls._member_names_)
-
- @property
- def __members__(cls):
- """
- Returns a mapping of member name->value.
-
- This mapping lists all enum members, including aliases. Note that this
- is a read-only view of the internal mapping.
- """
- return MappingProxyType(cls._member_map_)
-
- def __repr__(cls):
- return "<enum %r>" % cls.__name__
-
- def __reversed__(cls):
- """
- Returns members in reverse definition order.
- """
- return (cls._member_map_[name] for name in reversed(cls._member_names_))
-
- def __setattr__(cls, name, value):
- """
- Block attempts to reassign Enum members.
-
- A simple assignment to the class namespace only changes one of the
- several possible ways to get an Enum member from the Enum class,
- resulting in an inconsistent Enumeration.
- """
- member_map = cls.__dict__.get('_member_map_', {})
- if name in member_map:
- raise AttributeError('Cannot reassign members.')
- super().__setattr__(name, value)
-
- def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
- """
- Convenience method to create a new Enum class.
-
- `names` can be:
-
- * A string containing member names, separated either with spaces or
- commas. Values are incremented by 1 from `start`.
- * An iterable of member names. Values are incremented by 1 from `start`.
- * An iterable of (member name, value) pairs.
- * A mapping of member name -> value pairs.
- """
- metacls = cls.__class__
- bases = (cls, ) if type is None else (type, cls)
- _, first_enum = cls._get_mixins_(cls, bases)
- classdict = metacls.__prepare__(class_name, bases)
-
- # special processing needed for names?
- if isinstance(names, str):
- names = names.replace(',', ' ').split()
- if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
- original_names, names = names, []
- last_values = []
- for count, name in enumerate(original_names):
- value = first_enum._generate_next_value_(name, start, count, last_values[:])
- last_values.append(value)
- names.append((name, value))
-
- # Here, names is either an iterable of (name, value) or a mapping.
- for item in names:
- if isinstance(item, str):
- member_name, member_value = item, names[item]
- else:
- member_name, member_value = item
- classdict[member_name] = member_value
- enum_class = metacls.__new__(metacls, class_name, bases, classdict)
-
- # TODO: replace the frame hack if a blessed way to know the calling
- # module is ever developed
- if module is None:
- try:
- module = sys._getframe(2).f_globals['__name__']
- except (AttributeError, ValueError, KeyError):
- pass
- if module is None:
- _make_class_unpicklable(enum_class)
- else:
- enum_class.__module__ = module
- if qualname is not None:
- enum_class.__qualname__ = qualname
-
- return enum_class
-
- def _convert_(cls, name, module, filter, source=None):
- """
- Create a new Enum subclass that replaces a collection of global constants
- """
- # convert all constants from source (or module) that pass filter() to
- # a new Enum called name, and export the enum and its members back to
- # module;
- # also, replace the __reduce_ex__ method so unpickling works in
- # previous Python versions
- module_globals = vars(sys.modules[module])
- if source:
- source = vars(source)
- else:
- source = module_globals
- # _value2member_map_ is populated in the same order every time
- # for a consistent reverse mapping of number to name when there
- # are multiple names for the same number.
- members = [
- (name, value)
- for name, value in source.items()
- if filter(name)]
- try:
- # sort by value
- members.sort(key=lambda t: (t[1], t[0]))
- except TypeError:
- # unless some values aren't comparable, in which case sort by name
- members.sort(key=lambda t: t[0])
- cls = cls(name, members, module=module)
- cls.__reduce_ex__ = _reduce_ex_by_name
- module_globals.update(cls.__members__)
- module_globals[name] = cls
- return cls
-
- @staticmethod
- def _check_for_existing_members(class_name, bases):
- for chain in bases:
- for base in chain.__mro__:
- if issubclass(base, Enum) and base._member_names_:
- raise TypeError(
- "%s: cannot extend enumeration %r"
- % (class_name, base.__name__)
- )
-
- @staticmethod
- def _get_mixins_(class_name, bases):
- """
- Returns the type for creating enum members, and the first inherited
- enum class.
-
- bases: the tuple of bases that was given to __new__
- """
- if not bases:
- return object, Enum
-
- def _find_data_type(bases):
- data_types = set()
- for chain in bases:
- candidate = None
- for base in chain.__mro__:
- if base is object:
- continue
- elif issubclass(base, Enum):
- if base._member_type_ is not object:
- data_types.add(base._member_type_)
- break
- elif '__new__' in base.__dict__:
- if issubclass(base, Enum):
- continue
- data_types.add(candidate or base)
- break
- else:
- candidate = candidate or base
- if len(data_types) > 1:
- raise TypeError('%r: too many data types: %r' % (class_name, data_types))
- elif data_types:
- return data_types.pop()
- else:
- return None
-
- # ensure final parent class is an Enum derivative, find any concrete
- # data type, and check that Enum has no members
- first_enum = bases[-1]
- if not issubclass(first_enum, Enum):
- raise TypeError("new enumerations should be created as "
- "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
- member_type = _find_data_type(bases) or object
- if first_enum._member_names_:
- raise TypeError("Cannot extend enumerations")
- return member_type, first_enum
-
- @staticmethod
- def _find_new_(classdict, member_type, first_enum):
- """
- Returns the __new__ to be used for creating the enum members.
-
- classdict: the class dictionary given to __new__
- member_type: the data type whose __new__ will be used by default
- first_enum: enumeration to check for an overriding __new__
- """
- # now find the correct __new__, checking to see of one was defined
- # by the user; also check earlier enum classes in case a __new__ was
- # saved as __new_member__
- __new__ = classdict.get('__new__', None)
-
- # should __new__ be saved as __new_member__ later?
- save_new = __new__ is not None
-
- if __new__ is None:
- # check all possibles for __new_member__ before falling back to
- # __new__
- for method in ('__new_member__', '__new__'):
- for possible in (member_type, first_enum):
- target = getattr(possible, method, None)
- if target not in {
- None,
- None.__new__,
- object.__new__,
- Enum.__new__,
- }:
- __new__ = target
- break
- if __new__ is not None:
- break
- else:
- __new__ = object.__new__
-
- # if a non-object.__new__ is used then whatever value/tuple was
- # assigned to the enum member name will be passed to __new__ and to the
- # new enum member's __init__
- if __new__ is object.__new__:
- use_args = False
- else:
- use_args = True
- return __new__, save_new, use_args
-
-
-class Enum(metaclass=EnumMeta):
- """
- Generic enumeration.
-
- Derive from this class to define new enumerations.
- """
- def __new__(cls, value):
- # all enum instances are actually created during class construction
- # without calling this method; this method is called by the metaclass'
- # __call__ (i.e. Color(3) ), and by pickle
- if type(value) is cls:
- # For lookups like Color(Color.RED)
- return value
- # by-value search for a matching enum member
- # see if it's in the reverse mapping (for hashable values)
- try:
- return cls._value2member_map_[value]
- except KeyError:
- # Not found, no need to do long O(n) search
- pass
- except TypeError:
- # not there, now do long search -- O(n) behavior
- for member in cls._member_map_.values():
- if member._value_ == value:
- return member
- # still not found -- try _missing_ hook
- try:
- exc = None
- result = cls._missing_(value)
- except Exception as e:
- exc = e
- result = None
- try:
- if isinstance(result, cls):
- return result
- else:
- ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- if result is None and exc is None:
- raise ve_exc
- elif exc is None:
- exc = TypeError(
- 'error in %s._missing_: returned %r instead of None or a valid member'
- % (cls.__name__, result)
- )
- if not isinstance(exc, ValueError):
- exc.__context__ = ve_exc
- raise exc
- finally:
- # ensure all variables that could hold an exception are destroyed
- exc = None
- ve_exc = None
-
- def _generate_next_value_(name, start, count, last_values):
- """
- Generate the next value when not given.
-
- name: the name of the member
- start: the initial start value or None
- count: the number of existing members
- last_value: the last value assigned or None
- """
- for last_value in reversed(last_values):
- try:
- return last_value + 1
- except TypeError:
- pass
- else:
- return start
-
- @classmethod
- def _missing_(cls, value):
- return None
-
- def __repr__(self):
- return "<%s.%s: %r>" % (
- self.__class__.__name__, self._name_, self._value_)
-
- def __str__(self):
- return "%s.%s" % (self.__class__.__name__, self._name_)
-
- def __dir__(self):
- """
- Returns all members and all public methods
- """
- added_behavior = [
- m
- for cls in self.__class__.mro()
- for m in cls.__dict__
- if m[0] != '_' and m not in self._member_map_
- ] + [m for m in self.__dict__ if m[0] != '_']
- return (['__class__', '__doc__', '__module__'] + added_behavior)
-
- def __format__(self, format_spec):
- """
- Returns format using actual value type unless __str__ has been overridden.
- """
- # mixed-in Enums should use the mixed-in type's __format__, otherwise
- # we can get strange results with the Enum name showing up instead of
- # the value
-
- # pure Enum branch, or branch with __str__ explicitly overridden
- str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__)
- if self._member_type_ is object or str_overridden:
- cls = str
- val = str(self)
- # mix-in branch
- else:
- cls = self._member_type_
- val = self._value_
- return cls.__format__(val, format_spec)
-
- def __hash__(self):
- return hash(self._name_)
-
- def __reduce_ex__(self, proto):
- return self.__class__, (self._value_, )
-
- # DynamicClassAttribute is used to provide access to the `name` and
- # `value` properties of enum members while keeping some measure of
- # protection from modification, while still allowing for an enumeration
- # to have members named `name` and `value`. This works because enumeration
- # members are not set directly on the enum class -- __getattr__ is
- # used to look them up.
-
- @DynamicClassAttribute
- def name(self):
- """The name of the Enum member."""
- return self._name_
-
- @DynamicClassAttribute
- def value(self):
- """The value of the Enum member."""
- return self._value_
-
-
-class IntEnum(int, Enum):
- """Enum where members are also (and must be) ints"""
-
-
-def _reduce_ex_by_name(self, proto):
- return self.name
-
-class Flag(Enum):
- """
- Support for flags
- """
-
- def _generate_next_value_(name, start, count, last_values):
- """
- Generate the next value when not given.
-
- name: the name of the member
- start: the initial start value or None
- count: the number of existing members
- last_value: the last value assigned or None
- """
- if not count:
- return start if start is not None else 1
- for last_value in reversed(last_values):
- try:
- high_bit = _high_bit(last_value)
- break
- except Exception:
- raise TypeError('Invalid Flag value: %r' % last_value) from None
- return 2 ** (high_bit+1)
-
- @classmethod
- def _missing_(cls, value):
- """
- Returns member (possibly creating it) if one can be found for value.
- """
- original_value = value
- if value < 0:
- value = ~value
- possible_member = cls._create_pseudo_member_(value)
- if original_value < 0:
- possible_member = ~possible_member
- return possible_member
-
- @classmethod
- def _create_pseudo_member_(cls, value):
- """
- Create a composite member iff value contains only members.
- """
- pseudo_member = cls._value2member_map_.get(value, None)
- if pseudo_member is None:
- # verify all bits are accounted for
- _, extra_flags = _decompose(cls, value)
- if extra_flags:
- raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- # construct a singleton enum pseudo-member
- pseudo_member = object.__new__(cls)
- pseudo_member._name_ = None
- pseudo_member._value_ = value
- # use setdefault in case another thread already created a composite
- # with this value
- pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
- return pseudo_member
-
- def __contains__(self, other):
- """
- Returns True if self has at least the same flags set as other.
- """
- if not isinstance(other, self.__class__):
- raise TypeError(
- "unsupported operand type(s) for 'in': '%s' and '%s'" % (
- type(other).__qualname__, self.__class__.__qualname__))
- return other._value_ & self._value_ == other._value_
-
- def __repr__(self):
- cls = self.__class__
- if self._name_ is not None:
- return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
- members, uncovered = _decompose(cls, self._value_)
- return '<%s.%s: %r>' % (
- cls.__name__,
- '|'.join([str(m._name_ or m._value_) for m in members]),
- self._value_,
- )
-
- def __str__(self):
- cls = self.__class__
- if self._name_ is not None:
- return '%s.%s' % (cls.__name__, self._name_)
- members, uncovered = _decompose(cls, self._value_)
- if len(members) == 1 and members[0]._name_ is None:
- return '%s.%r' % (cls.__name__, members[0]._value_)
- else:
- return '%s.%s' % (
- cls.__name__,
- '|'.join([str(m._name_ or m._value_) for m in members]),
- )
-
- def __bool__(self):
- return bool(self._value_)
-
- def __or__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ | other._value_)
-
- def __and__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ & other._value_)
-
- def __xor__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ ^ other._value_)
-
- def __invert__(self):
- members, uncovered = _decompose(self.__class__, self._value_)
- inverted = self.__class__(0)
- for m in self.__class__:
- if m not in members and not (m._value_ & self._value_):
- inverted = inverted | m
- return self.__class__(inverted)
-
-
-class IntFlag(int, Flag):
- """
- Support for integer-based Flags
- """
-
- @classmethod
- def _missing_(cls, value):
- """
- Returns member (possibly creating it) if one can be found for value.
- """
- if not isinstance(value, int):
- raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- new_member = cls._create_pseudo_member_(value)
- return new_member
-
- @classmethod
- def _create_pseudo_member_(cls, value):
- """
- Create a composite member iff value contains only members.
- """
- pseudo_member = cls._value2member_map_.get(value, None)
- if pseudo_member is None:
- need_to_create = [value]
- # get unaccounted for bits
- _, extra_flags = _decompose(cls, value)
- # timer = 10
- while extra_flags:
- # timer -= 1
- bit = _high_bit(extra_flags)
- flag_value = 2 ** bit
- if (flag_value not in cls._value2member_map_ and
- flag_value not in need_to_create
- ):
- need_to_create.append(flag_value)
- if extra_flags == -flag_value:
- extra_flags = 0
- else:
- extra_flags ^= flag_value
- for value in reversed(need_to_create):
- # construct singleton pseudo-members
- pseudo_member = int.__new__(cls, value)
- pseudo_member._name_ = None
- pseudo_member._value_ = value
- # use setdefault in case another thread already created a composite
- # with this value
- pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
- return pseudo_member
-
- def __or__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- result = self.__class__(self._value_ | self.__class__(other)._value_)
- return result
-
- def __and__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- return self.__class__(self._value_ & self.__class__(other)._value_)
-
- def __xor__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- return self.__class__(self._value_ ^ self.__class__(other)._value_)
-
- __ror__ = __or__
- __rand__ = __and__
- __rxor__ = __xor__
-
- def __invert__(self):
- result = self.__class__(~self._value_)
- return result
-
-
-def _high_bit(value):
- """
- returns index of highest bit, or -1 if value is zero or negative
- """
- return value.bit_length() - 1
-
-def unique(enumeration):
- """
- Class decorator for enumerations ensuring unique member values.
- """
- duplicates = []
- for name, member in enumeration.__members__.items():
- if name != member.name:
- duplicates.append((name, member.name))
- if duplicates:
- alias_details = ', '.join(
- ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
- raise ValueError('duplicate values found in %r: %s' %
- (enumeration, alias_details))
- return enumeration
-
-def _decompose(flag, value):
- """
- Extract all members from the value.
- """
- # _decompose is only called if the value is not named
- not_covered = value
- negative = value < 0
- members = []
- for member in flag:
- member_value = member.value
- if member_value and member_value & value == member_value:
- members.append(member)
- not_covered &= ~member_value
- if not negative:
- tmp = not_covered
- while tmp:
- flag_value = 2 ** _high_bit(tmp)
- if flag_value in flag._value2member_map_:
- members.append(flag._value2member_map_[flag_value])
- not_covered &= ~flag_value
- tmp &= ~flag_value
- if not members and value in flag._value2member_map_:
- members.append(flag._value2member_map_[value])
- members.sort(key=lambda m: m._value_, reverse=True)
- if len(members) > 1 and members[0].value == value:
- # we have the breakdown, don't need the value member itself
- members.pop(0)
- return members, not_covered
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py
index 92bc30d2b..7a0871ee7 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py
@@ -1,6 +1,9 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+# flake8: noqa F:821
+# flake8: noqa F:401
+
"""
__feature__.py (renamed to feature.py)
@@ -15,9 +18,10 @@ The normal usage is like
Alternatively, there is the `set_selection` function which uses select_id's
and takes an optional `mod_name` parameter.
-The select id `-1` has the spectial meaning "ignore this module".
+The select id `-1` has the special meaning "ignore this module".
"""
+import inspect
import sys
from contextlib import contextmanager
@@ -79,11 +83,13 @@ None to indicate that a normal import should be performed, and
All these variables are transparently kept in module `builtins`.
"""
+
def feature_import(name, *args, **kwargs):
# PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
# PYSIDE-1398: sys._getframe(1) may not exist when embedding.
# PYSIDE-1338: The "1" below is the redirection in loader.py .
# PYSIDE-1548: Ensure that features are not affected by other imports.
+ # PYSIDE-2029: Need to always switch. The cache was wrong interpreted.
calling_frame = _cf = sys._getframe(1).f_back
importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__"
existing = pyside_feature_dict.get(importing_module, 0)
@@ -105,27 +111,68 @@ def feature_import(name, *args, **kwargs):
# Initialize feature (multiple times allowed) and clear cache.
sys.modules["PySide6.QtCore"].__init_feature__()
return sys.modules["__feature__"]
-
- if importing_module not in pyside_feature_dict:
- # Ignore new modules if not from PySide.
- default = 0 if name.split(".")[0] == "PySide6" else -1
- pyside_feature_dict[importing_module] = default
# Redirect to the original import
return None
+
_is_initialized = False
+
def __init__():
global _is_initialized
if not _is_initialized:
# use _one_ recursive import...
import PySide6.QtCore
# Initialize all prior imported modules
- for name in sys.modules:
- pyside_feature_dict.setdefault(name, -1)
+ for name, module in sys.modules.items():
+ if name not in pyside_feature_dict:
+ pyside_feature_dict[name] = 0 if _mod_uses_pyside(module) else -1
_is_initialized = True
+def feature_imported(module):
+ # PYSIDE-2029: Need to inspect imported modules for PySide usage.
+ """
+ Set the module feature default after import.
+
+ A module that uses PySide has a switching default of 0 = "no feature".
+ Otherwise the default is -1 = "ignore this module".
+ """
+
+ # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
+ if hasattr(module, "__name__"):
+ name = module.__name__
+ if name not in pyside_feature_dict:
+ pyside_feature_dict[name] = 0 if _mod_uses_pyside(module) else -1
+
+
+def _mod_uses_pyside(module):
+ """
+ Find out if this module uses PySide.
+
+ Simple approach: Search the source code for the string "PySide6".
+ Maybe we later support source-less modules by inspecting all code objects.
+ """
+ try:
+ source = inspect.getsource(module)
+ except TypeError:
+ # this is a builtin module like sys
+ return False
+ except OSError:
+ # this is a module withot source file
+ return False
+ except SyntaxError:
+ # PYSIDE-2189: A UnicodeError happens in tokenize.py in find_cookie
+ # which is then creating a SyntaxError in inspect.
+ # This is undocumented and a Python error, seen in Python 3.10.2 on Windows,
+ # importing `pythoncom` of the win32 package.
+ return False
+ except Exception:
+ # PYSIDE-2393: pytest behaves weird when allowing any other error.
+ return False
+ return "PySide6" in source
+
+
def set_selection(select_id, mod_name=None):
"""
Internal use: Set the feature directly by Id.
@@ -141,6 +188,7 @@ def set_selection(select_id, mod_name=None):
sys.modules["PySide6.QtCore"].__init_feature__()
return _current_selection(flag)
+
# The set_section(0) case seems to be unsafe. We will migrate to
# use the opaque feature.reset() call in all test cases.
def reset():
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
index 3e1d49328..f7190b12f 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
@@ -9,7 +9,6 @@ Run it once after copying a new version. It is idem-potent, unless
you are changing messages (what I did, of course :-) .
"""
-import os
import glob
from pathlib import Path
@@ -24,6 +23,7 @@ offending_words = {
utf8_line = "# This Python file uses the following encoding: utf-8\n"
marker_line = f"# It has been edited by {Path(__file__).name} .\n"
+
def patch_file(fname):
with fname.open() as f:
lines = f.readlines()
@@ -41,6 +41,7 @@ def patch_file(fname):
with open(fname, "w") as f:
f.write("".join(lines))
+
def doit():
dirname = Path(__file__).parent
patched_files = []
@@ -51,6 +52,7 @@ def doit():
print("Working on", fname)
patch_file(fname)
+
if __name__ == "__main__":
doit()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
index a08143968..7147a4148 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
@@ -1,6 +1,5 @@
{
"files": ["__init__.py",
- "enum_310.py",
"feature.py",
"fix-complaints.py",
"signature/__init__.py",
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
index 6b428e613..c2a19efef 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
@@ -1,6 +1,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+# flake8: noqa E:721
+
"""
errorhandler.py
@@ -19,12 +21,10 @@ This matter will be improved in a later version.
"""
import collections.abc
-import inspect
-import sys
import typing
from shibokensupport.signature import get_signature
-from shibokensupport.signature.mapping import update_mapping, namespace
+from shibokensupport.signature.mapping import namespace
from textwrap import dedent
@@ -77,8 +77,8 @@ def seterror_argument(args, func_name, info):
if info == "<":
msg = f"{func_name}(): not enough arguments"
elif info == "0":
- msg = (f"{func_name}(): not enough arguments. "
- "Note: keyword arguments are only supported for optional parameters.")
+ msg = (f"{func_name}(): not enough arguments. "
+ "Note: keyword arguments are only supported for optional parameters.")
elif info == ">":
msg = f"{func_name}(): too many arguments"
elif info.isalnum():
@@ -87,6 +87,12 @@ def seterror_argument(args, func_name, info):
msg = f"{func_name}(): {info}"
err = AttributeError
return err, msg
+ if isinstance(info, Exception):
+ # PYSIDE-2230: Python 3.12 seems to always do normalization.
+ err = type(info)
+ info = info.args[0]
+ msg = f"{func_name}(): {info}"
+ return err, msg
if info and type(info) is dict:
msg = f"{func_name}(): unsupported keyword '{tuple(info)[0]}'"
return AttributeError, msg
@@ -126,6 +132,8 @@ def check_string_type(s):
def make_helptext(func):
existing_doc = func.__doc__
+ if existing_doc is None and hasattr(func, "__dict__"):
+ existing_doc = func.__dict__.get("__doc__")
sigs = get_signature(func)
if not sigs:
return existing_doc
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
index dbde18f18..bae264294 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
@@ -34,9 +34,10 @@ def finish_import(module):
except Exception as e:
name = e.__class__.__qualname__
print(72 * "*")
- print(f"Error in deprecated.py, ignored:")
+ print("Error in deprecated.py, ignored:")
print(f" {name}: {e}")
+
"""
A note for people who might think this could be written in pure Python:
@@ -62,4 +63,3 @@ module, it is *perhaps* possible to solve that. I tried for a day and then
gave up, since the solution is anyway not too nice when __import__ must
be overridden.
"""
-#eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index d7dfa3451..0e781cbcb 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -79,6 +79,7 @@ class SignatureLayout(SimpleNamespace):
The only allowed values are '{allowed_values}'.
"""))
+
# The following names are used literally in this module.
# This way, we avoid the dict hashing problem.
signature = SignatureLayout()
@@ -115,7 +116,7 @@ def define_nameless_parameter():
P = inspect.Parameter
newname = "NamelessParameter"
bases = P.__bases__
- body = dict(P.__dict__) # get rid of mappingproxy
+ body = dict(P.__dict__) # get rid of mappingproxy
if "__slots__" in body:
# __slots__ would create duplicates
for name in body["__slots__"]:
@@ -167,12 +168,13 @@ def make_signature_nameless(signature):
signature.parameters[key].__class__ = NamelessParameter
-_POSITIONAL_ONLY = inspect._POSITIONAL_ONLY
-_POSITIONAL_OR_KEYWORD = inspect._POSITIONAL_OR_KEYWORD
-_VAR_POSITIONAL = inspect._VAR_POSITIONAL
-_KEYWORD_ONLY = inspect._KEYWORD_ONLY
-_VAR_KEYWORD = inspect._VAR_KEYWORD
-_empty = inspect._empty
+_POSITIONAL_ONLY = inspect._POSITIONAL_ONLY # noqa E:201
+_POSITIONAL_OR_KEYWORD = inspect._POSITIONAL_OR_KEYWORD # noqa E:201
+_VAR_POSITIONAL = inspect._VAR_POSITIONAL # noqa E:201
+_KEYWORD_ONLY = inspect._KEYWORD_ONLY # noqa E:201
+_VAR_KEYWORD = inspect._VAR_KEYWORD # noqa E:201
+_empty = inspect._empty # noqa E:201
+
def create_signature(props, key):
if not props:
@@ -183,9 +185,9 @@ def create_signature(props, key):
return list(create_signature(elem, key)
for elem in props["multi"])
if type(key) is tuple:
- sig_kind, modifier = key
+ _, modifier = key
else:
- sig_kind, modifier = key, "signature"
+ _, modifier = key, "signature"
layout = globals()[modifier] # lookup of the modifier in this module
if not isinstance(layout, SignatureLayout):
@@ -200,7 +202,7 @@ def create_signature(props, key):
# parser.
pass
else:
- if varnames[0] in ("self", "cls"):
+ if varnames and varnames[0] in ("self", "cls"):
varnames = varnames[1:]
# calculate the modifications
@@ -234,8 +236,8 @@ def create_signature(props, key):
if kind == _VAR_POSITIONAL:
kind = _KEYWORD_ONLY
sig = inspect.Signature(params,
- return_annotation=annotations.get('return', _empty),
- __validate_parameters__=False)
+ return_annotation=annotations.get('return', _empty),
+ __validate_parameters__=False)
# the special case of nameless parameters
if not layout.parameter_names:
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
index 779ac2b4a..5650e2bc1 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
@@ -14,9 +14,7 @@ by producing a lot of clarity.
import inspect
import sys
import types
-import typing
from shibokensupport.signature import get_signature as get_sig
-from shibokensupport.signature.layout import create_signature
"""
@@ -38,6 +36,10 @@ if hasattr(sys, "pypy_version_info"):
_normal_functions += (type(get_sig),)
+def signal_check(thing):
+ return thing and type(thing) in (Signal, SignalInstance)
+
+
class ExactEnumerator(object):
"""
ExactEnumerator enumerates all signatures in a module as they are.
@@ -48,13 +50,13 @@ class ExactEnumerator(object):
"""
def __init__(self, formatter, result_type=dict):
- global EnumMeta
+ global EnumMeta, Signal, SignalInstance
try:
# Lazy import
- from PySide6.QtCore import Qt
+ from PySide6.QtCore import Qt, Signal, SignalInstance
EnumMeta = type(Qt.Key)
except ImportError:
- EnumMeta = None
+ EnumMeta = Signal = SignalInstance = None
self.fmt = formatter
self.result_type = result_type
@@ -102,7 +104,7 @@ class ExactEnumerator(object):
return ret
if "<" in class_name:
# This is happening in QtQuick for some reason:
- ## class QSharedPointer<QQuickItemGrabResult >:
+ # class std::shared_ptr<QQuickItemGrabResult >:
# We simply skip over this class.
return ret
bases_list = []
@@ -120,9 +122,19 @@ class ExactEnumerator(object):
functions = []
enums = []
properties = []
+ signals = []
+ attributes = {}
for thing_name, thing in class_members:
- if inspect.isclass(thing):
+ if signal_check(thing):
+ signals.append((thing_name, thing))
+ elif inspect.isclass(thing):
+ # If this is the only member of the class, it causes the stub
+ # to be printed empty without ..., as self.fmt.have_body will
+ # then be True. (Example: QtCore.QCborTag). Skip it to avoid
+ # this problem.
+ if thing_name == "_member_type_":
+ continue
subclass_name = ".".join((class_name, thing_name))
subclasses.append((subclass_name, thing))
elif inspect.isroutine(thing):
@@ -130,22 +142,32 @@ class ExactEnumerator(object):
functions.append((func_name, thing))
elif type(type(thing)) is EnumMeta:
# take the real enum name, not what is in the dict
- enums.append((thing_name, type(thing).__qualname__, thing))
+ if not thing_name.startswith("_"):
+ enums.append((thing_name, type(thing).__qualname__, thing))
elif isinstance(thing, property):
properties.append((thing_name, thing))
+ # Support attributes that have PySide types as values,
+ # but we skip the 'staticMetaObject' that needs
+ # to be defined at a QObject level.
+ elif "PySide" in str(type(thing)) and "QMetaObject" not in str(type(thing)):
+ if class_name not in attributes:
+ attributes[class_name] = {}
+ attributes[class_name][thing_name] = thing
if thing_name in self.collision_candidates:
self.collision_track.add(thing_name)
init_signature = getattr(klass, "__signature__", None)
- enums.sort(key=lambda tup: tup[1 : 3]) # sort by class then enum value
+ # sort by class then enum value
+ enums.sort(key=lambda tup: (tup[1], tup[2].value))
# We want to handle functions and properties together.
func_prop = sorted(functions + properties, key=lambda tup: tup[0])
# find out how many functions create a signature
sigs = list(_ for _ in functions if get_sig(_[1]))
- self.fmt.have_body = bool(subclasses or sigs or properties or enums or init_signature)
+ self.fmt.have_body = bool(subclasses or sigs or properties or enums or # noqa W:504
+ init_signature or signals or attributes)
with self.fmt.klass(class_name, class_str):
self.fmt.level += 1
@@ -155,8 +177,25 @@ class ExactEnumerator(object):
if len(enums):
self.section()
for enum_name, enum_class_name, value in enums:
- with self.fmt.enum(enum_class_name, enum_name, int(value)):
+ with self.fmt.enum(enum_class_name, enum_name, value.value):
+ pass
+ if hasattr(self.fmt, "signal"):
+ # this is an optional feature
+ if len(signals):
+ self.section()
+ for signal_name, signal in signals:
+ sig_class = type(signal)
+ sig_class_name = f"{sig_class.__qualname__}"
+ sig_str = str(signal)
+ with self.fmt.signal(sig_class_name, signal_name, sig_str):
pass
+ if hasattr(self.fmt, "attribute"):
+ if len(attributes):
+ self.section()
+ for class_name, attrs in attributes.items():
+ for attr_name, attr_value in attrs.items():
+ with self.fmt.attribute(attr_name, attr_value):
+ pass
if len(subclasses):
self.section()
for subclass_name, subclass in subclasses:
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
index 292b83fae..ce12dd6c8 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
@@ -3,6 +3,8 @@ LICENSE_TEXT = """
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
+# flake8: noqa E:402
+
"""
pyi_generator.py
@@ -21,7 +23,6 @@ from pathlib import Path
from contextlib import contextmanager
from textwrap import dedent
-from shiboken6 import Shiboken
from shibokensupport.signature.lib.enum_sig import HintingEnumerator
from shibokensupport.signature.lib.tool import build_brace_pattern
@@ -59,6 +60,7 @@ class Formatter(Writer):
unrelated tasks of enumeration and formatting apart.
"""
def __init__(self, outfile, options, *args):
+ # XXX Find out which of these patches is still necessary!
self.options = options
Writer.__init__(self, outfile, *args)
# patching __repr__ to disable the __repr__ of typing.TypeVar:
@@ -74,8 +76,12 @@ class Formatter(Writer):
"""
def _typevar__repr__(self):
return f"typing.{self.__name__}"
- typing.TypeVar.__repr__ = _typevar__repr__
-
+ # This is no longer necessary for modern typing versions.
+ # Ignore therefore if the repr is read-only and cannot be changed.
+ try:
+ typing.TypeVar.__repr__ = _typevar__repr__
+ except TypeError:
+ pass
# Adding a pattern to substitute "Union[T, NoneType]" by "Optional[T]"
# I tried hard to replace typing.Optional by a simple override, but
# this became _way_ too much.
@@ -84,6 +90,7 @@ class Formatter(Writer):
pattern = fr"\b Union \s* \[ \s* {brace_pat} \s*, \s* NoneType \s* \]"
replace = r"Optional[\1]"
optional_searcher = re.compile(pattern, flags=re.VERBOSE)
+
def optional_replacer(source):
return optional_searcher.sub(replace, str(source))
self.optional_replacer = optional_replacer
@@ -151,6 +158,18 @@ class Formatter(Writer):
self.print(f"{spaces}{enum_name:25}: {class_name} = ... # {hexval}")
yield
+ @contextmanager
+ def attribute(self, attr_name, attr_value):
+ spaces = indent * self.level
+ self.print(f"{spaces}{attr_name:25} = ... # type: {type(attr_value).__qualname__}")
+ yield
+
+ @contextmanager
+ def signal(self, class_name, sig_name, sig_str):
+ spaces = indent * self.level
+ self.print(f"{spaces}{sig_name:25}: ClassVar[{class_name}] = ... # {sig_str}")
+ yield
+
def find_imports(text):
return [imp for imp in PySide6.__all__ if f"PySide6.{imp}." in text]
@@ -159,12 +178,14 @@ def find_imports(text):
FROM_IMPORTS = [
(None, ["builtins"]),
(None, ["os"]),
- (None, ["enum"] if sys.pyside63_option_python_enum else []),
- ("typing", typing.__all__),
- ("PySide6.QtCore", ["PyClassProperty"]),
+ (None, ["enum"]),
+ ("collections.abc", ["Iterable"]),
+ ("typing", sorted(typing.__all__)),
+ ("PySide6.QtCore", ["PyClassProperty", "Signal", "SignalInstance"]),
("shiboken6", ["Shiboken"]),
]
+
def filter_from_imports(from_struct, text):
"""
Build a reduced new `from` structure (nfs) with found entries, only
@@ -174,8 +195,15 @@ def filter_from_imports(from_struct, text):
lis = []
nfs.append((mod, lis))
for each in imports:
- if re.search(rf"(\b|@){each}\b([^\s\(:]|\n)", text):
- lis.append(each)
+ # PYSIDE-1603: We search text that is a usage of the class `each`,
+ # but only if the class is not also defined here.
+ if (f"class {each}(") not in text:
+ if re.search(rf"(\b|@){each}\b([^\s\(:]|\n)", text):
+ lis.append(each)
+ # Search if a type is present in the return statement
+ # of function declarations: '... -> here:'
+ if re.search(rf"->.*{each}.*:", text):
+ lis.append(each)
if not lis:
nfs.pop()
return nfs
@@ -214,12 +242,10 @@ def generate_pyi(import_name, outpath, options):
obj = getattr(top, plainname) if import_name != plainname else top
if not getattr(obj, "__file__", None) or Path(obj.__file__).is_dir():
raise ModuleNotFoundError(f"We do not accept a namespace as module `{plainname}`")
- module = sys.modules[import_name]
outfile = io.StringIO()
fmt = Formatter(outfile, options)
fmt.print(LICENSE_TEXT.strip())
- need_imports = options._pyside_call and not USE_PEP563
if USE_PEP563:
fmt.print("from __future__ import annotations")
fmt.print()
@@ -261,13 +287,12 @@ def generate_pyi(import_name, outpath, options):
wr.print(f"from {mod} import {import_args}")
wr.print()
wr.print()
+ wr.print("NoneType: TypeAlias = type[None]")
+ wr.print()
else:
wr.print(line)
if not options.quiet:
options.logger.info(f"Generated: {outfilepath}")
- # PYSIDE-1735: .pyi files are no longer compatible with Python, because
- # enum classes contain ellipsis which a Python enum forbids.
- # We will implement tests with Mypy, instead.
def main():
@@ -282,11 +307,10 @@ def main():
pyi_generator will try to generate an interface "<module>.pyi".
"""))
parser.add_argument("module",
- help="The full path name of an importable module binary (.pyd, .so)")
+ help="The full path name of an importable module binary (.pyd, .so)") # noqa E:128
parser.add_argument("--quiet", action="store_true", help="Run quietly")
- parser.add_argument("--check", action="store_true", help="Test the output")
parser.add_argument("--outpath",
- help="the output directory (default = location of module binary)")
+ help="the output directory (default = location of module binary)") # noqa E:128
options = parser.parse_args()
module = options.module
outpath = options.outpath
@@ -304,6 +328,7 @@ def main():
options.logger = logger
generate_pyi(module, outpath, options=options)
+
if __name__ == "__main__":
main()
# eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
index a7900e6b2..979dcf4ce 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
@@ -44,8 +44,8 @@ def build_brace_pattern(level, separators):
ro, rc = round_ = "()"
so, sc = square = "[]"
- co, cc = curly = "CD" # we insert "{}", later...
- ao, ac = angle = "<>"
+ co, cc = curly = "CD" # noqa E:201 we insert "{}", later...
+ ao, ac = angle = "<>" # noqa E:201
q2, bs, q1 = '"', "\\", "'"
allpat = round_ + square + curly + angle
__ = " "
@@ -79,8 +79,8 @@ def build_brace_pattern(level, separators):
{indent} )*
""")
for idx in range(level):
- pattern = pattern.format(replacer = repeated if idx < level-1 else no_braces_q,
- indent = idx * " ", **locals())
+ pattern = pattern.format(replacer=repeated if idx < level - 1 else no_braces_q,
+ indent=idx * " ", **locals())
return pattern.replace("C", "{").replace("D", "}")
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
index aa2fa3adb..fb4c9eeca 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
@@ -1,6 +1,9 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+# flake8: noqa E:402
+# flake8: noqa F:401
+
"""
loader.py
@@ -30,22 +33,27 @@ import types
def pyside_type_init(type_key, sig_strings):
return parser.pyside_type_init(type_key, sig_strings)
+
# name used in signature.cpp
def create_signature(props, key):
return layout.create_signature(props, key)
+
# name used in signature.cpp
def seterror_argument(args, func_name, info):
return errorhandler.seterror_argument(args, func_name, info)
+
# name used in signature.cpp
def make_helptext(func):
return errorhandler.make_helptext(func)
+
# name used in signature.cpp
def finish_import(module):
return importhandler.finish_import(module)
+
# name used in signature.cpp
def feature_import(*args, **kwds):
# don't spend a stack level here for speed and compatibility
@@ -54,6 +62,14 @@ def feature_import(*args, **kwds):
return feature_import(*args, **kwds)
+# name used in signature.cpp
+def feature_imported(*args, **kwds):
+ # don't spend a stack level here for speed and compatibility
+ global feature_imported
+ feature_imported = feature.feature_imported
+ return feature_imported(*args, **kwds)
+
+
import builtins
import signature_bootstrap
from shibokensupport import signature, feature
@@ -100,6 +116,7 @@ def move_into_pyside_package():
put_into_package(PySide6.support.signature.lib, pyi_generator)
put_into_package(PySide6.support.signature.lib, tool)
+
from shibokensupport.signature import mapping
from shibokensupport.signature import errorhandler
from shibokensupport.signature import layout
@@ -109,13 +126,10 @@ from shibokensupport.signature import importhandler
from shibokensupport.signature.lib import enum_sig
from shibokensupport.signature.lib import pyi_generator
from shibokensupport.signature.lib import tool
-if sys.version_info[:2] < (3, 10):
- # PYSIDE-1735: Use the faster and more complete enum implementation.
- from shibokensupport import enum_310 as enum
- sys.modules["enum"] = enum
- # compatibility
- if sys.version_info[:2] < (3, 8):
- enum.Enum._convert = classmethod(enum.EnumMeta._convert_)
+
+import enum
+
+post_init = lambda: None # noqa E:731 default
if "PySide6" in sys.modules:
# We publish everything under "PySide6.support", again.
@@ -123,17 +137,22 @@ if "PySide6" in sys.modules:
# PYSIDE-1502: Make sure that support can be imported.
try:
import PySide6.support
- except ModuleNotFoundError as e:
+ except ModuleNotFoundError:
print("PySide6.support could not be imported. "
"This is a serious configuration error.", file=sys.stderr)
raise
- # PYSIDE-1019: Modify `__import__` to be `__feature__` aware.
- # __feature__ is already in sys.modules as feature, so this is actually no import
- if not is_pypy:
- # PYSIDE-535: Cannot enable __feature__ for various reasons.
- import PySide6.support.feature
- sys.modules["__feature__"] = PySide6.support.feature
- builtins.__orig_import__ = builtins.__import__
- builtins.__import__ = builtins.__feature_import__
+
+ def post_init():
+ """
+ This function needs to be called explicitly when all function pointers are set.
+ Doing this during import has bad side-effects when preloading the loader.
+ """
+ # PYSIDE-1019: Modify `__import__` to be `__feature__` aware.
+ if not is_pypy:
+ # PYSIDE-535: Cannot enable __feature__ for various reasons.
+ import PySide6.support.feature
+ sys.modules["__feature__"] = PySide6.support.feature
+ builtins.__orig_import__ = builtins.__import__
+ builtins.__import__ = builtins.__feature_import__
# end of file
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 2118d7e39..944a928e6 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -1,6 +1,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+# flake8: noqa E:203
+
"""
mapping.py
@@ -20,12 +22,14 @@ from pathlib import Path
from typing import TypeVar, Generic
from _imp import is_builtin
+
class ellipsis(object):
def __repr__(self):
return "..."
+
ellipsis = ellipsis()
-Point = typing.Tuple[float, float]
+Point = typing.Tuple[int, int]
Variant = typing.Any
QImageCleanupFunction = typing.Callable
@@ -38,7 +42,7 @@ _S = TypeVar("_S")
MultiMap = typing.DefaultDict[str, typing.List[str]]
# ulong_max is only 32 bit on windows.
-ulong_max = 2*sys.maxsize+1 if len(struct.pack("L", 1)) != 4 else 0xffffffff
+ulong_max = 2 * sys.maxsize + 1 if len(struct.pack("L", 1)) != 4 else 0xffffffff
ushort_max = 0xffff
GL_COLOR_BUFFER_BIT = 0x00004000
@@ -74,6 +78,7 @@ class _NotCalled(str):
text = self if self.endswith(")") else self + "()"
return eval(text, namespace)
+
USE_PEP563 = False
# Note: we cannot know if this feature has been imported.
# Otherwise it would be "sys.version_info[:2] >= (3, 7)".
@@ -86,6 +91,7 @@ USE_PEP563 = False
class Virtual(_NotCalled):
pass
+
# Other types I simply could not find.
class Missing(_NotCalled):
# The string must be quoted, because the object does not exist.
@@ -98,6 +104,7 @@ class Missing(_NotCalled):
class Invalid(_NotCalled):
pass
+
# Helper types
class Default(_NotCalled):
pass
@@ -106,6 +113,7 @@ class Default(_NotCalled):
class Instance(_NotCalled):
pass
+
# Parameterized primitive variables
class _Parameterized(object):
def __init__(self, type):
@@ -115,15 +123,18 @@ class _Parameterized(object):
def __repr__(self):
return f"{type(self).__name__}({self.type.__name__})"
+
# Mark the primitive variables to be moved into the result.
class ResultVariable(_Parameterized):
pass
+
# Mark the primitive variables to become Sequence, Iterable or List
# (decided in the parser).
class ArrayLikeVariable(_Parameterized):
pass
+
StringList = ArrayLikeVariable(str)
@@ -142,7 +153,7 @@ class Reloader(object):
if getattr(mod, "__file__", None) and not Path(mod.__file__).is_dir():
ending = Path(mod.__file__).suffix
return ending not in (".py", ".pyc", ".pyo", ".pyi")
- return bool(is_builtin(mod.__name__))
+ return bool(hasattr(mod, "__name__") and is_builtin(mod.__name__))
def update(self):
"""
@@ -180,12 +191,14 @@ def check_module(mod):
mod_name = mod.__name__
raise ImportError(f"Module '{mod_name}' is not a binary module!")
+
update_mapping = Reloader().update
type_map = {}
namespace = globals() # our module's __dict__
type_map.update({
"...": ellipsis,
+ "Any": typing.Any,
"bool": bool,
"char": int,
"double": float,
@@ -200,7 +213,7 @@ type_map.update({
"PyObject": object,
"PyObject*": object,
"PyArrayObject": ArrayLikeVariable, # numpy
- "PyPathLike": typing.Union[str, bytes, os.PathLike],
+ "PyPathLike": typing.Union[str, bytes, os.PathLike[str]],
"PySequence": typing.Iterable, # important for numpy
"PyTypeObject": type,
"QChar": str,
@@ -217,6 +230,7 @@ type_map.update({
"uintptr_t": int,
"qintptr": int,
"qsizetype": int,
+ "QFunctionPointer": int,
"QList": ArrayLikeVariable,
"qlonglong": int,
"QMap": typing.Dict,
@@ -227,6 +241,7 @@ type_map.update({
"qreal": float,
"QSet": typing.Set,
"QString": str,
+ "QLatin1String": str,
"QStringView": str,
"QStringList": StringList,
"quint16": int,
@@ -238,6 +253,7 @@ type_map.update({
"uint32_t": int,
"uint64_t": int,
"uint8_t": int,
+ "Union": typing.Union,
"quintptr": int,
"qulonglong": int,
"QVariant": Variant,
@@ -263,16 +279,16 @@ type_map.update({
"ulong": int,
"ULONG_MAX": ulong_max,
"UINT64_MAX": 0xffffffff,
- "unsigned char": int, # 5.9
+ "unsigned char": int, # 5.9
"unsigned char*": str,
"unsigned int": int,
- "unsigned long int": int, # 5.6, RHEL 6.6
+ "unsigned long int": int, # 5.6, RHEL 6.6
"unsigned long long": int,
"unsigned long": int,
- "unsigned short int": int, # 5.6, RHEL 6.6
+ "unsigned short int": int, # 5.6, RHEL 6.6
"unsigned short": int,
"ushort": int,
- "void": int, # be more specific?
+ "void": int, # be more specific?
"WId": WId,
"zero(bytes)": b"",
"zero(Char)": 0,
@@ -282,7 +298,11 @@ type_map.update({
"zero(str)": "",
"zero(typing.Any)": None,
"zero(Any)": None,
- })
+ # This can be refined by importing numpy.typing optionally, but better than nothing.
+ "numpy.ndarray": typing.List[typing.Any],
+ "std.array[int, 4]": typing.List[int],
+ "std.array[float, 4]": typing.List[float]
+})
type_map.update({
# Handling variables declared as array:
@@ -294,8 +314,8 @@ type_map.update({
"array long long*" : ArrayLikeVariable(int),
"array long*" : ArrayLikeVariable(int),
"array short*" : ArrayLikeVariable(int),
- "array signed char*" : bytes,
- "array unsigned char*" : bytes,
+ "array signed char*" : typing.Union[bytes, bytearray, memoryview],
+ "array unsigned char*" : typing.Union[bytes, bytearray, memoryview],
"array unsigned int*" : ArrayLikeVariable(int),
"array unsigned short*" : ArrayLikeVariable(int),
# PYSIDE-1646: New macOS primitive types
@@ -306,17 +326,17 @@ type_map.update({
"array int32_t*" : ArrayLikeVariable(int),
"array uint32_t*" : ArrayLikeVariable(int),
"array intptr_t*" : ArrayLikeVariable(int),
- })
+})
type_map.update({
# Special cases:
- "char*" : bytes,
- "QChar*" : bytes,
+ "char*" : typing.Union[bytes, bytearray, memoryview],
+ "QChar*" : typing.Union[bytes, bytearray, memoryview],
"quint32*" : int, # only for QRandomGenerator
"quint8*" : bytearray, # only for QCborStreamReader and QCborValue
- "uchar*" : bytes,
- "unsigned char*": bytes,
- })
+ "uchar*" : typing.Union[bytes, bytearray, memoryview],
+ "unsigned char*": typing.Union[bytes, bytearray, memoryview],
+})
type_map.update({
# Handling variables that are returned, eventually as Tuples:
@@ -338,7 +358,7 @@ type_map.update({
"uint*" : ResultVariable(int),
"unsigned int*" : ResultVariable(int),
"QStringList*" : ResultVariable(StringList),
- })
+})
type_map.update({
@@ -346,20 +366,21 @@ type_map.update({
"[typing.Any]" : [typing.Any],
"[typing.Any,typing.Any]" : [typing.Any, typing.Any],
"None" : None,
- })
+})
# PYSIDE-1328: We need to handle "self" explicitly.
type_map.update({
"self" : "self",
"cls" : "cls",
- })
+})
# PYSIDE-1538: We need to treat "std::optional" accordingly.
type_map.update({
"std.optional": typing.Optional,
})
+
# The Shiboken Part
def init_Shiboken():
type_map.update({
@@ -369,6 +390,7 @@ def init_Shiboken():
})
return locals()
+
def init_minimal():
type_map.update({
"MinBool": bool,
@@ -384,7 +406,7 @@ def init_sample():
"const char*": str,
"Complex": complex,
"double": float,
- "ByteArray&": bytes,
+ "ByteArray&": typing.Union[bytes, bytearray, memoryview],
"Foo.HANDLE": int,
"HANDLE": int,
"Null": None,
@@ -392,7 +414,7 @@ def init_sample():
"OddBool": bool,
"PStr": str,
"PyDate": datetime.date,
- "PyBuffer": bytes,
+ "PyBuffer": typing.Union[bytes, bytearray, memoryview],
"sample.bool": bool,
"sample.char": int,
"sample.double": float,
@@ -428,6 +450,7 @@ def init_smart():
# This missing type should be defined in module smart. We cannot set it to Missing()
# because it is a container type. Therefore, we supply a surrogate:
global SharedPtr
+
class SharedPtr(Generic[_S]):
__module__ = "smart"
smart.SharedPtr = SharedPtr
@@ -440,8 +463,8 @@ def init_smart():
# The PySide Part
def init_PySide6_QtCore():
from PySide6.QtCore import Qt, QUrl, QDir, QKeyCombination
- from PySide6.QtCore import QRect, QSize, QPoint, QLocale, QByteArray
- from PySide6.QtCore import QMarginsF # 5.9
+ from PySide6.QtCore import QRect, QRectF, QSize, QPoint, QLocale, QByteArray
+ from PySide6.QtCore import QMarginsF # 5.9
from PySide6.QtCore import SignalInstance
try:
# seems to be not generated by 5.9 ATM.
@@ -452,40 +475,41 @@ def init_PySide6_QtCore():
"' '": " ",
"'%'": "%",
"'g'": "g",
- "4294967295UL": 4294967295, # 5.6, RHEL 6.6
+ "4294967295UL": 4294967295, # 5.6, RHEL 6.6
"CheckIndexOption.NoOption": Instance(
- "PySide6.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
+ "PySide6.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
"DescriptorType(-1)": int, # Native handle of QSocketDescriptor
"false": False,
"list of QAbstractAnimation": typing.List[PySide6.QtCore.QAbstractAnimation],
"long long": int,
"size_t": int,
- "NULL": None, # 5.6, MSVC
- "nullptr": None, # 5.9
- "PyBuffer": bytes,
+ "NULL": None, # 5.6, MSVC
+ "nullptr": None, # 5.9
+ "PyBuffer": typing.Union[bytes, bytearray, memoryview],
"PyByteArray": bytearray,
- "PyBytes": bytes,
+ "PyBytes": typing.Union[bytes, bytearray, memoryview],
"PyTuple": typing.Tuple,
"QDeadlineTimer(QDeadlineTimer.Forever)": Instance("PySide6.QtCore.QDeadlineTimer"),
"PySide6.QtCore.QUrl.ComponentFormattingOptions":
- PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
+ PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
"PyUnicode": typing.Text,
"QByteArrayView": QByteArray,
"Q_NULLPTR": None,
"QCalendar.Unspecified": PySide6.QtCore.QCalendar.Unspecified,
+ "QCborTag(-1)": ulong_max,
"QDir.Filters(AllEntries | NoDotAndDotDot)": Instance(
"QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot)"),
"QDir.SortFlags(Name | IgnoreCase)": Instance(
"QDir.SortFlags(QDir.Name | QDir.IgnoreCase)"),
- "QEvent.Type.None" : None,
- "QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
+ "QEvent.Type.None": None,
+ "QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
"QGenericArgument()": ellipsis,
"QGenericArgument(0)": ellipsis,
- "QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
- "QGenericArgument(nullptr)": ellipsis, # 5.10
+ "QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
+ "QGenericArgument(nullptr)": ellipsis, # 5.10
"QGenericArgument(Q_NULLPTR)": ellipsis,
"QJsonObject": typing.Dict[str, PySide6.QtCore.QJsonValue],
- "QModelIndex()": Invalid("PySide6.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
+ "QModelIndex()": Invalid("PySide6.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
"QModelIndexList": typing.List[PySide6.QtCore.QModelIndex],
"PySideSignalInstance": SignalInstance,
"QString()": "",
@@ -493,17 +517,17 @@ def init_PySide6_QtCore():
"QStringList()": [],
"QStringRef": str,
"QStringRef": str,
- "Qt.HANDLE": int, # be more explicit with some constants?
+ "Qt.HANDLE": int, # be more explicit with some constants?
"QUrl.FormattingOptions(PrettyDecoded)": Instance(
"QUrl.FormattingOptions(QUrl.PrettyDecoded)"),
"QVariant()": Invalid(Variant),
- "QVariant.Type": type, # not so sure here...
- "QVariantMap": typing.Dict[str, Variant],
+ "QVariant.Type": type, # not so sure here...
"QVariantMap": typing.Dict[str, Variant],
+ "std.chrono.seconds{5}" : ellipsis,
})
try:
type_map.update({
- "PySide6.QtCore.QMetaObject.Connection": PySide6.QtCore.Connection, # wrong!
+ "PySide6.QtCore.QMetaObject.Connection": PySide6.QtCore.Connection, # wrong!
})
except AttributeError:
# this does not exist on 5.9 ATM.
@@ -528,7 +552,7 @@ def init_PySide6_QtConcurrent():
def init_PySide6_QtGui():
- from PySide6.QtGui import QPageLayout, QPageSize # 5.12 macOS
+ from PySide6.QtGui import QPageLayout, QPageSize # 5.12 macOS
type_map.update({
"0.0f": 0.0,
"1.0f": 1.0,
@@ -537,10 +561,11 @@ def init_PySide6_QtGui():
"int32_t": int,
"HBITMAP": int,
"HICON": int,
+ "HMONITOR": int,
"HRGN": int,
- "QPixmap()": Default("PySide6.QtGui.QPixmap"), # can't create without qApp
- "QPlatformSurface*": int, # a handle
- "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
+ "QPixmap()": Default("PySide6.QtGui.QPixmap"), # can't create without qApp
+ "QPlatformSurface*": int, # a handle
+ "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
"uint32_t": int,
"uint8_t": int,
"USHRT_MAX": ushort_max,
@@ -554,8 +579,9 @@ def init_PySide6_QtGui():
def init_PySide6_QtWidgets():
- from PySide6.QtWidgets import QWidget, QMessageBox, QStyleOption, QStyleHintReturn, QStyleOptionComplex
- from PySide6.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem # 5.9
+ from PySide6.QtWidgets import (QWidget, QMessageBox, QStyleOption,
+ QStyleHintReturn, QStyleOptionComplex,
+ QGraphicsItem, QStyleOptionGraphicsItem)
type_map.update({
"QMessageBox.StandardButtons(Yes | No)": Instance(
"QMessageBox.StandardButtons(QMessageBox.Yes | QMessageBox.No)"),
@@ -576,7 +602,7 @@ def init_PySide6_QtSql():
from PySide6.QtSql import QSqlDatabase
type_map.update({
"QLatin1StringView(QSqlDatabase.defaultConnection)": QSqlDatabase.defaultConnection,
- "QVariant.Invalid": Invalid("Variant"), # not sure what I should create, here...
+ "QVariant.Invalid": Invalid("Variant"), # not sure what I should create, here...
})
return locals()
@@ -600,7 +626,7 @@ def init_PySide6_QtOpenGL():
type_map.update({
"GLbitfield": int,
"GLenum": int,
- "GLfloat": float, # 5.6, MSVC 15
+ "GLfloat": float, # 5.6, MSVC 15
"GLint": int,
"GLuint": int,
})
@@ -657,9 +683,36 @@ def init_PySide6_QtBluetooth():
return locals()
+def init_PySide6_QtGraphs():
+ from PySide6.QtGraphs import (QBarDataItem, QSurfaceDataItem)
+ QBarDataRow = typing.List[QBarDataItem]
+ QBarDataArray = typing.List[QBarDataRow]
+ QSurfaceDataRow = typing.List[QSurfaceDataItem]
+ QSurfaceDataArray = typing.List[QSurfaceDataRow]
+ type_map.update({
+ "100.0f": 100.0,
+ "QBarDataArray": QBarDataArray,
+ "QBarDataArray*": QBarDataArray,
+ "QSurfaceDataArray": QSurfaceDataArray,
+ "QSurfaceDataArray*": QSurfaceDataArray,
+ })
+ return locals()
+
+
+def init_PySide6_QtHttpServer():
+ type_map.update({
+ "qMakePair(1u, 1u)": (1, 1),
+ })
+ return locals()
+
+
def init_testbinding():
type_map.update({
"testbinding.PySideCPP2.TestObjectWithoutNamespace": testbinding.TestObjectWithoutNamespace,
+ "testbinding.FlagsNamespace.Options": testbinding.Option,
+ "FlagsNamespace.Option.NoOptions": 0,
+ "StdIntList": typing.List[int],
+ 'Str("")': str(""),
})
return locals()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 4c8ade025..9b48ab442 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -1,21 +1,19 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+import ast
import enum
-import functools
import keyword
import os
import re
import sys
-import types
import typing
import warnings
from types import SimpleNamespace
from shibokensupport.signature.mapping import (type_map, update_mapping,
- namespace, _NotCalled, ResultVariable, ArrayLikeVariable)
+ namespace, _NotCalled, ResultVariable, ArrayLikeVariable) # noqa E:128
from shibokensupport.signature.lib.tool import build_brace_pattern
-from shibokensupport import feature
_DEBUG = False
LIST_KEYWORDS = False
@@ -40,8 +38,9 @@ guesses, we provide an entry in 'type_map' that resolves it.
In effect, 'type_map' maps text to real Python objects.
"""
+
def _get_flag_enum_option():
- from shiboken6 import (__version_info__ as ver,
+ from shiboken6 import (__version_info__ as ver, # noqa F:401
__minimum_python_version__ as pyminver,
__maximum_python_version__ as pymaxver)
@@ -49,7 +48,7 @@ def _get_flag_enum_option():
# This decides between delivered vs. dev versions.
# When 6.4 is out, the switching mode will be gone.
flag = ver[:2] >= (6, 4)
- envname = "PYSIDE63_OPTION_PYTHON_ENUM"
+ envname = "PYSIDE6_OPTION_PYTHON_ENUM"
sysname = envname.lower()
opt = os.environ.get(envname)
if opt:
@@ -58,26 +57,35 @@ def _get_flag_enum_option():
flag = True
elif opt in ("no", "off", "false"):
flag = False
- elif opt.isnumeric():
- flag = bool(int(opt))
+ else:
+ # instead of a simple int() conversion, let's allow for "0xf" or "0b1111"
+ try:
+ flag = ast.literal_eval(opt)
+ except Exception:
+ flag = False # turn a forbidden option into an error
elif hasattr(sys, sysname):
- flag = bool(getattr(sys, sysname))
- # PYSIDE-1797: Emit a warning when we may remove pep384_issue33738.cpp
- if pyminver and pyminver >= (3, 8):
- warnings.warn(f"\n *** Python is at version {'.'.join(map(str, pyminver))} now. "
- f"The file pep384_issue33738.cpp should be removed ASAP! ***")
- # PYSIDE-1735: Emit a warning when we may update enum_310.py
- if pymaxver and pymaxver > (3, 10):
- warnings.warn(f"\n *** Python is at version {'.'.join(map(str, pymaxver))} now. "
- f"Please check if enum_310.py should be updated! ***")
- # PYSIDE-1735: Emit a warning when we may update enum_310.py
+ opt2 = flag = getattr(sys, sysname)
+ if not isinstance(flag, int):
+ flag = False # turn a forbidden option into an error
+ p = f"\n *** Python is at version {'.'.join(map(str, pyminver or (0,)))} now."
+ q = f"\n *** PySide is at version {'.'.join(map(str, ver[:2]))} now."
+ # _PepUnicode_AsString: Fix a broken promise
+ if pyminver and pyminver >= (3, 10):
+ warnings.warn(f"{p} _PepUnicode_AsString can now be replaced by PyUnicode_AsUTF8! ***")
+ # PYSIDE-1960: Emit a warning when we may remove bufferprocs_py37.(cpp|h)
+ if pyminver and pyminver >= (3, 11):
+ warnings.warn(f"{p} The files bufferprocs_py37.(cpp|h) should be removed ASAP! ***")
+ # PYSIDE-1735: Emit a warning when we should maybe evict forgiveness mode
if ver[:2] >= (7, 0):
- warnings.warn(f"\n *** PySide is at version {'.'.join(map(str, ver[:2]))} now. "
- f"Please drop the forgiving Enum behavior in `mangled_type_getattro` ***")
- # modify the sys attribute to bool
+ warnings.warn(f"{q} Please drop Enum forgiveness mode in `mangled_type_getattro` ***")
+ # PYSIDE-2404: Emit a warning when we should drop uppercase offset constants
+ if ver[:2] >= (7, 0):
+ warnings.warn(f"{q} Please drop uppercase type offsets in `copyOffsetEnumStream` ***")
+ # normalize the sys attribute
setattr(sys, sysname, flag)
- # modify the env attribute to "0" or "1"
- os.environ[envname] = str(int(flag))
+ os.environ[envname] = str(flag)
+ if int(flag) == 0:
+ raise RuntimeError(f"Old Enums are no longer supported. int({opt or opt2}) evaluates to 0)")
return flag
@@ -99,6 +107,7 @@ def dprint(*args, **kw):
_cache = {}
+
def _parse_arglist(argstr):
# The following is a split re. The string is broken into pieces which are
# between the recognized strings. Because the re has groups, both the
@@ -180,7 +189,7 @@ def _handle_instance_fixup(thing):
if not match:
return thing
start, stop = match.start(), match.end() - 1
- pre, func, args = thing[:start], thing[start : stop], thing[stop:]
+ pre, func, args = thing[:start], thing[start:stop], thing[stop:]
if func[0].isupper() or func.startswith("gl") and func[2:3].isupper():
return thing
# Now convert this string to snake case.
@@ -189,7 +198,7 @@ def _handle_instance_fixup(thing):
if char.isupper():
if idx and func[idx - 1].isupper():
# two upper chars are forbidden
- return things
+ return thing
snake_func += f"_{char.lower()}"
else:
snake_func += char
@@ -232,12 +241,14 @@ def try_to_guess(thing, valtype):
return ret
return None
+
def get_name(thing):
if isinstance(thing, type):
return getattr(thing, "__qualname__", thing.__name__)
else:
return thing.__name__
+
def _resolve_value(thing, valtype, line):
if thing in ("0", "None") and valtype:
if valtype.startswith("PySide6.") or valtype.startswith("typing."):
@@ -290,7 +301,7 @@ def to_string(thing):
dot = "." in str(thing) or m not in (thing.__qualname__, "builtins")
name = get_name(thing)
ret = m + "." + name if dot else name
- assert(eval(ret, globals(), namespace))
+ assert (eval(ret, globals(), namespace))
return ret
# Note: This captures things from the typing module:
return str(thing)
@@ -298,8 +309,9 @@ def to_string(thing):
matrix_pattern = "PySide6.QtGui.QGenericMatrix"
+
def handle_matrix(arg):
- n, m, typstr = tuple(map(lambda x:x.strip(), arg.split(",")))
+ n, m, typstr = tuple(map(lambda x: x.strip(), arg.split(",")))
assert typstr == "float"
result = f"PySide6.QtGui.QMatrix{n}x{m}"
return eval(result, globals(), namespace)
@@ -327,13 +339,13 @@ def _resolve_type(thing, line, level, var_handler, func_name=None):
# Special case: Handle the generic matrices.
if contr == matrix_pattern:
return handle_matrix(thing)
- contr = var_handler(_resolve_type(contr, line, level+1, var_handler))
+ contr = var_handler(_resolve_type(contr, line, level + 1, var_handler))
if isinstance(contr, _NotCalled):
raise SystemError("Container types must exist:", repr(contr))
contr = to_string(contr)
pieces = []
for part in _parse_arglist(thing):
- part = var_handler(_resolve_type(part, line, level+1, var_handler))
+ part = var_handler(_resolve_type(part, line, level + 1, var_handler))
if isinstance(part, _NotCalled):
# fix the tag (i.e. "Missing") by repr
part = repr(part)
@@ -343,7 +355,7 @@ def _resolve_type(thing, line, level, var_handler, func_name=None):
# PYSIDE-1538: Make sure that the eval does not crash.
try:
return eval(result, globals(), namespace)
- except Exception as e:
+ except Exception:
warnings.warn(f"""pyside_type_init:_resolve_type
UNRECOGNIZED: {result!r}
@@ -393,18 +405,6 @@ def handle_retvar(obj):
def calculate_props(line):
- # PYSIDE-1735: QFlag is now divided into fields for future Python Enums, like
- # "PySide.QtCore.^^Qt.ItemFlags^^Qt.ItemFlag^^"
- # Resolve that until Enum is finally settled.
- while "^^" in line:
- parts = line.split("^^", 3)
- selected = EnumSelect.SELECTION
- line = parts[0] + parts[selected.value] + parts[3]
- if selected is EnumSelect.NEW:
- _old, _new = EnumSelect.OLD.value, EnumSelect.NEW.value
- line = re.sub(rf"\b{parts[_old]}\b", parts[_new], line)
- type_map[parts[_old]] = parts[_new]
-
parsed = SimpleNamespace(**_parse_line(line.strip()))
arglist = parsed.arglist
annotations = {}
@@ -434,9 +434,9 @@ def calculate_props(line):
props.defaults = defaults
props.kwdefaults = {}
props.annotations = annotations
- props.varnames = varnames = tuple(tup[0] for tup in arglist)
+ props.varnames = tuple(tup[0] for tup in arglist)
funcname = parsed.funcname
- shortname = funcname[funcname.rindex(".")+1:]
+ shortname = funcname[funcname.rindex(".") + 1:]
props.name = shortname
props.multi = parsed.multi
fix_variables(props, line)
@@ -482,7 +482,6 @@ def fix_variables(props, line):
else:
diff -= 1
if retvars:
- rvs = []
retvars = list(handle_retvar(rv) if isinstance(rv, ArrayLikeVariable) else rv
for rv in retvars)
if len(retvars) == 1:
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
index e261bf271..0f05aea8b 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
@@ -3,7 +3,7 @@
"Name": "Python",
"QDocModule": "QtForPython",
"QtUsage": "Used for Qt for Python in the signature extension.",
- "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files (enum_310.py). See the folder sources/shiboken6/files.dir/shibokensupport .",
+ "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files. See the folder sources/shiboken6/files.dir/shibokensupport .",
"Homepage": "http://www.python.org/",
"Version": "3.7.0",
"LicenseId": "Python-2.0",
diff --git a/sources/shiboken6/shibokenmodule/shibokenmodule.cpp b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp
new file mode 100644
index 000000000..5c6219885
--- /dev/null
+++ b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp
@@ -0,0 +1,119 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+// @snippet isvalid
+bool isValid = Shiboken::Object::isValid(%1, false);
+%PYARG_0 = %CONVERTTOPYTHON[bool](isValid);
+// @snippet isvalid
+
+// @snippet wrapinstance
+auto *pyType = reinterpret_cast<PyTypeObject *>(%2);
+if (Shiboken::ObjectType::checkType(pyType)) {
+ auto *ptr = reinterpret_cast<void *>(%1);
+ if (auto *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(ptr)) {
+ Py_INCREF(wrapper);
+ %PYARG_0 = reinterpret_cast<PyObject *>(wrapper);
+ } else {
+ %PYARG_0 = Shiboken::Object::newObject(pyType, ptr, false, true);
+ }
+} else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+}
+// @snippet wrapinstance
+
+// @snippet getcpppointer
+if (Shiboken::Object::checkType(%1)) {
+ std::vector<void*> ptrs = Shiboken::Object::cppPointers(reinterpret_cast<SbkObject *>(%1));
+ %PYARG_0 = PyTuple_New(ptrs.size());
+ for (std::size_t i = 0; i < ptrs.size(); ++i)
+ PyTuple_SET_ITEM(%PYARG_0, i, PyLong_FromVoidPtr(ptrs[i]));
+} else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+}
+// @snippet getcpppointer
+
+// @snippet delete
+if (Shiboken::Object::checkType(%1)) {
+ Shiboken::Object::callCppDestructors(reinterpret_cast<SbkObject *>(%1));
+} else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+}
+// @snippet delete
+
+// @snippet ownedbypython
+if (Shiboken::Object::checkType(%1)) {
+ bool hasOwnership = Shiboken::Object::hasOwnership(reinterpret_cast<SbkObject *>(%1));
+ %PYARG_0 = %CONVERTTOPYTHON[bool](hasOwnership);
+} else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+}
+// @snippet ownedbypython
+
+// @snippet createdbypython
+if (Shiboken::Object::checkType(%1)) {
+ bool wasCreatedByPython = Shiboken::Object::wasCreatedByPython(reinterpret_cast<SbkObject *>(%1));
+ %PYARG_0 = %CONVERTTOPYTHON[bool](wasCreatedByPython);
+} else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+}
+// @snippet createdbypython
+
+// @snippet disassembleframe
+Shiboken::AutoDecRef label(PyObject_Str(%1));
+const char *marker = Shiboken::String::toCString(label);
+disassembleFrame(marker);
+Py_INCREF(Py_None);
+%PYARG_0 = Py_None;
+// @snippet disassembleframe
+
+// @snippet dump
+if (!Shiboken::Object::checkType(%1)) {
+ %PYARG_0 = Shiboken::String::fromCString("Ordinary Python type.");
+} else {
+ std::string str = Shiboken::Object::info(reinterpret_cast<SbkObject *>(%1));
+ %PYARG_0 = Shiboken::String::fromCString(str.c_str());
+}
+// @snippet dump
+
+// @snippet getallvalidwrappers
+const auto setAll = Shiboken::BindingManager::instance().getAllPyObjects();
+PyObject* listAll = PyList_New(0);
+if (listAll == nullptr)
+ return nullptr;
+for (auto *o : setAll) {
+ if (o != nullptr) {
+ if (PyList_Append(listAll, o) != 0) {
+ Py_DECREF(listAll);
+ return nullptr;
+ }
+ }
+}
+return listAll;
+// @snippet getallvalidwrappers
+
+// @snippet dumptypegraph
+const bool ok = Shiboken::BindingManager::instance().dumpTypeGraph(%1);
+%PYARG_0 = %CONVERTTOPYTHON[bool](ok);
+// @snippet dumptypegraph
+
+// @snippet dumpwrappermap
+Shiboken::BindingManager::instance().dumpWrapperMap();
+// @snippet dumpwrappermap
+
+// @snippet dumpconverters
+Shiboken::Conversions::dumpConverters();
+// @snippet dumpconverters
+
+// @snippet init
+// Add __version__ and __version_info__ attributes to the module
+PyObject* version = PyTuple_New(5);
+PyTuple_SET_ITEM(version, 0, PyLong_FromLong(SHIBOKEN_MAJOR_VERSION));
+PyTuple_SET_ITEM(version, 1, PyLong_FromLong(SHIBOKEN_MINOR_VERSION));
+PyTuple_SET_ITEM(version, 2, PyLong_FromLong(SHIBOKEN_MICRO_VERSION));
+PyTuple_SET_ITEM(version, 3, Shiboken::String::fromCString(SHIBOKEN_RELEASE_LEVEL));
+PyTuple_SET_ITEM(version, 4, PyLong_FromLong(SHIBOKEN_SERIAL));
+PyModule_AddObject(module, "__version_info__", version);
+PyModule_AddStringConstant(module, "__version__", SHIBOKEN_VERSION);
+VoidPtr::addVoidPtrToModule(module);
+Shiboken::initShibokenSupport(module);
+// @snippet init
diff --git a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
index 1bee3f543..acb522ecc 100644
--- a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
+++ b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" ?>
+<!--
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+-->
<typesystem package="Shiboken">
<primitive-type name="bool" />
<primitive-type name="unsigned long" />
<primitive-type name="size_t" />
<add-function signature="isValid(PyObject*)" return-type="bool">
- <inject-code>
- bool isValid = Shiboken::Object::isValid(%1, false);
- %PYARG_0 = %CONVERTTOPYTHON[bool](isValid);
- </inject-code>
+ <inject-code file="shibokenmodule.cpp" snippet="isvalid"/>
</add-function>
<add-function signature="invalidate(PyObject*)">
@@ -17,116 +18,53 @@
</add-function>
<add-function signature="wrapInstance(size_t, PyTypeObject)" return-type="PyObject*">
- <inject-code>
- auto *pyType = reinterpret_cast&lt;PyTypeObject *&gt;(%2);
- if (Shiboken::ObjectType::checkType(pyType)) {
- %PYARG_0 = Shiboken::Object::newObject(pyType,
- reinterpret_cast&lt;void *&gt;(%1),
- false, true);
- } else {
- PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
- }
- </inject-code>
+ <inject-code file="shibokenmodule.cpp" snippet="wrapinstance"/>
</add-function>
- <add-function signature="getCppPointer(PyObject*)" return-type="PyObject*">
- <inject-code>
- if (Shiboken::Object::checkType(%1)) {
- std::vector&lt;void*> ptrs = Shiboken::Object::cppPointers(reinterpret_cast&lt;SbkObject *&gt;(%1));
- %PYARG_0 = PyTuple_New(ptrs.size());
- for (std::size_t i = 0; i &lt; ptrs.size(); ++i)
- PyTuple_SET_ITEM(%PYARG_0, i, PyLong_FromVoidPtr(ptrs[i]));
- } else {
- PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
- }
- </inject-code>
+ <add-function signature="getCppPointer(PyObject*)" return-type="PySequence*">
+ <inject-code file="shibokenmodule.cpp" snippet="getcpppointer"/>
</add-function>
<add-function signature="delete(PyObject*)">
- <inject-code>
- if (Shiboken::Object::checkType(%1)) {
- Shiboken::Object::callCppDestructors(reinterpret_cast&lt;SbkObject *&gt;(%1));
- } else {
- PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
- }
- </inject-code>
+ <inject-code file="shibokenmodule.cpp" snippet="delete"/>
</add-function>
<add-function signature="ownedByPython(PyObject*)" return-type="bool">
- <inject-code>
- if (Shiboken::Object::checkType(%1)) {
- bool hasOwnership = Shiboken::Object::hasOwnership(reinterpret_cast&lt;SbkObject *&gt;(%1));
- %PYARG_0 = %CONVERTTOPYTHON[bool](hasOwnership);
- } else {
- PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
- }
- </inject-code>
+ <inject-code file="shibokenmodule.cpp" snippet="ownedbypython"/>
</add-function>
- <add-function signature="createdByPython(PyObject*)" return-type="bool">
- <inject-code>
- if (Shiboken::Object::checkType(%1)) {
- bool wasCreatedByPython = Shiboken::Object::wasCreatedByPython(reinterpret_cast&lt;SbkObject *&gt;(%1));
- %PYARG_0 = %CONVERTTOPYTHON[bool](wasCreatedByPython);
- } else {
- PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
- }
- </inject-code>
- </add-function>
+ <add-function signature="createdByPython(PyObject*)" return-type="bool">
+ <inject-code file="shibokenmodule.cpp" snippet="createdbypython"/>
+ </add-function>
- <add-function signature="dump(PyObject*)" return-type="PyObject*">
- <inject-code>
- if (!Shiboken::Object::checkType(%1)) {
- %PYARG_0 = Shiboken::String::fromCString("Ordinary Python type.");
- } else {
- std::string str = Shiboken::Object::info(reinterpret_cast&lt;SbkObject *&gt;(%1));
- %PYARG_0 = Shiboken::String::fromCString(str.c_str());
- }
- </inject-code>
+ <add-function signature="disassembleFrame(PyObject*)" return-type="PyObject">
+ <inject-code file="shibokenmodule.cpp" snippet="disassembleframe"/>
</add-function>
- <add-function signature="getAllValidWrappers(void)" return-type="PyObject*">
- <inject-code>
- std::set&lt;PyObject*&gt; setAll = Shiboken::BindingManager::instance().getAllPyObjects();
- PyObject* listAll = PyList_New(0);
- if (listAll == NULL)
- return NULL;
+ <add-function signature="dump(PyObject*)" return-type="const char *">
+ <inject-code file="shibokenmodule.cpp" snippet="dump"/>
+ </add-function>
- const std::set&lt;PyObject*&gt;::iterator end = setAll.end();
- for (std::set&lt;PyObject*&gt;::iterator iter = setAll.begin(); iter != end; ++iter) {
- if (*iter != NULL) {
- if (PyList_Append(listAll, *iter) != 0) {
- Py_DECREF(listAll);
- return NULL;
- }
- }
- }
- return listAll;
- </inject-code>
+ <add-function signature="getAllValidWrappers(void)" return-type="PySequence*">
+ <inject-code file="shibokenmodule.cpp" snippet="getallvalidwrappers"/>
</add-function>
- <add-function signature="_unpickle_enum(PyObject*, PyObject*)" return-type="PyObject*">
- <inject-code>
- %PYARG_0 = Shiboken::Enum::unpickleEnum(%1, %2);
- </inject-code>
+ <add-function signature="dumpTypeGraph(const char *@fileName@)" return-type="bool">
+ <inject-code file="shibokenmodule.cpp" snippet="dumptypegraph"/>
+ </add-function>
+
+ <add-function signature="dumpWrapperMap()">
+ <inject-code file="shibokenmodule.cpp" snippet="dumpwrappermap"/>
+ </add-function>
+
+ <add-function signature="dumpConverters()">
+ <inject-code file="shibokenmodule.cpp" snippet="dumpconverters"/>
</add-function>
<extra-includes>
<include file-name="sbkversion.h" location="local"/>
<include file-name="voidptr.h" location="local"/>
+ <include file-name="sbkconverter_p.h" location="local"/>
</extra-includes>
- <inject-code position="end">
- // Add __version__ and __version_info__ attributes to the module
- PyObject* version = PyTuple_New(5);
- PyTuple_SET_ITEM(version, 0, PyLong_FromLong(SHIBOKEN_MAJOR_VERSION));
- PyTuple_SET_ITEM(version, 1, PyLong_FromLong(SHIBOKEN_MINOR_VERSION));
- PyTuple_SET_ITEM(version, 2, PyLong_FromLong(SHIBOKEN_MICRO_VERSION));
- PyTuple_SET_ITEM(version, 3, Shiboken::String::fromCString(SHIBOKEN_RELEASE_LEVEL));
- PyTuple_SET_ITEM(version, 4, PyLong_FromLong(SHIBOKEN_SERIAL));
- PyModule_AddObject(module, "__version_info__", version);
- PyModule_AddStringConstant(module, "__version__", SHIBOKEN_VERSION);
-
- Shiboken::initSignature(module);
- VoidPtr::addVoidPtrToModule(module);
- </inject-code>
+ <inject-code position="end" file="shibokenmodule.cpp" snippet="init"/>
</typesystem>
diff --git a/sources/shiboken6/tests/CMakeLists.txt b/sources/shiboken6/tests/CMakeLists.txt
index 296f8d8d7..05f6e9e60 100644
--- a/sources/shiboken6/tests/CMakeLists.txt
+++ b/sources/shiboken6/tests/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
if(BUILD_TESTS)
find_package(Qt${QT_MAJOR_VERSION}Test 6.0 REQUIRED)
@@ -11,6 +14,8 @@ if(NOT DEFINED MINIMAL_TESTS)
add_subdirectory(libother)
endif()
+shiboken_get_debug_level(debug_level)
+
if(WIN32 OR DEFINED AVOID_PROTECTED_HACK)
message(STATUS "Tests will be generated avoiding the protected hack!")
set(GENERATOR_EXTRA_FLAGS --avoid-protected-hack)
@@ -18,6 +23,7 @@ else()
message(STATUS "Tests will be generated using the protected hack!")
set(GENERATOR_EXTRA_FLAGS )
endif()
+list(APPEND GENERATOR_EXTRA_FLAGS ${SHIBOKEN_GENERATOR_EXTRA_FLAGS} ${debug_level})
add_subdirectory(minimalbinding)
if(NOT DEFINED MINIMAL_TESTS)
@@ -40,13 +46,18 @@ list(SORT TEST_FILES)
set(test_blacklist "")
if(SHIBOKEN_IS_CROSS_BUILD)
- # PYTHON_EXECUTABLE will be empty when cross-building.
+ # Python_EXECUTABLE will be empty when cross-building.
message(WARNING
"Running tests when cross-compiling is not supported because it would require running "
"a target python interpreter which might have a different architecture than the host."
)
else()
- find_package(PythonInterp REQUIRED)
+ find_package(
+ Python
+ ${USE_PYTHON_VERSION}
+ REQUIRED
+ COMPONENTS Interpreter Development
+ )
endif()
if(NOT CTEST_TESTING_TIMEOUT)
@@ -60,7 +71,7 @@ foreach(test_file ${TEST_FILES})
string(REGEX MATCH "/([^/]+)(binding|module)/([^/]+)_test.py" tmp ${test_file})
set(test_name "${CMAKE_MATCH_1}_${CMAKE_MATCH_3}")
list(FIND test_blacklist ${test_name} expect_fail)
- add_test(${test_name} ${PYTHON_EXECUTABLE} ${test_file})
+ add_test(${test_name} ${Python_EXECUTABLE} ${test_file})
set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "BUILD_DIR=${BUILD_DIR}")
set_tests_properties(${test_name} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT})
if (${expect_fail} GREATER -1)
diff --git a/sources/shiboken6/tests/dumpcodemodel/CMakeLists.txt b/sources/shiboken6/tests/dumpcodemodel/CMakeLists.txt
index 44652e7e5..e7dbef961 100644
--- a/sources/shiboken6/tests/dumpcodemodel/CMakeLists.txt
+++ b/sources/shiboken6/tests/dumpcodemodel/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
add_executable(dumpcodemodel main.cpp)
target_include_directories(dumpcodemodel
@@ -9,5 +12,5 @@ target_include_directories(dumpcodemodel
target_link_libraries(dumpcodemodel
PRIVATE
apiextractor
- Qt${QT_MAJOR_VERSION}::Core
+ Qt::Core
)
diff --git a/sources/shiboken6/tests/dumpcodemodel/main.cpp b/sources/shiboken6/tests/dumpcodemodel/main.cpp
index 30f8fb798..eb876634c 100644
--- a/sources/shiboken6/tests/dumpcodemodel/main.cpp
+++ b/sources/shiboken6/tests/dumpcodemodel/main.cpp
@@ -12,6 +12,7 @@
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
+#include <QtCore/QLibraryInfo>
#include <QtCore/QVersionNumber>
#include <QtCore/QXmlStreamWriter>
@@ -19,12 +20,14 @@
#include <algorithm>
#include <iterator>
+using namespace Qt::StringLiterals;
+
static bool optJoinNamespaces = false;
static inline QString languageLevelDescription()
{
- return QLatin1String("C++ Language level (c++11..c++17, default=")
- + QLatin1String(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ return u"C++ Language level (c++11..c++20, default="_s
+ + QLatin1StringView(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ u')';
}
@@ -35,7 +38,7 @@ static void formatDebugOutput(const FileModelItem &dom, bool verbose)
QDebug debug(&output);
if (verbose)
debug.setVerbosity(3);
- debug << dom.data();
+ debug << dom.get();
}
std::cout << qPrintable(output) << '\n';
}
@@ -45,14 +48,14 @@ static const char *primitiveTypes[] = {
"float", "double"
};
-static inline QString nameAttribute() { return QStringLiteral("name"); }
+constexpr auto nameAttribute = "name"_L1;
static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass);
static void formatXmlEnum(QXmlStreamWriter &writer, const EnumModelItem &en)
{
- writer.writeStartElement(QStringLiteral("enum-type"));
- writer.writeAttribute(nameAttribute(), en->name());
+ writer.writeStartElement(u"enum-type"_s);
+ writer.writeAttribute(nameAttribute, en->name());
writer.writeEndElement();
}
@@ -92,9 +95,9 @@ static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass
const bool isValueType = std::any_of(functions.cbegin(), functions.cend(),
isPublicCopyConstructor);
formatXmlLocationComment(writer, klass);
- writer.writeStartElement(isValueType ? QStringLiteral("value-type")
- : QStringLiteral("object-type"));
- writer.writeAttribute(nameAttribute(), klass->name());
+ writer.writeStartElement(isValueType ? u"value-type"_s
+ : u"object-type"_s);
+ writer.writeAttribute(nameAttribute, klass->name());
formatXmlScopeMembers(writer, klass);
writer.writeEndElement();
}
@@ -114,14 +117,14 @@ static bool hasMembers(const NamespaceModelItem &nsp)
static void startXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp)
{
formatXmlLocationComment(writer, nsp);
- writer.writeStartElement(QStringLiteral("namespace-type"));
- writer.writeAttribute(nameAttribute(), nsp->name());
+ writer.writeStartElement(u"namespace-type"_s);
+ writer.writeAttribute(nameAttribute, nsp->name());
}
static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceModelItem &nsp)
{
auto nestedNamespaces = nsp->namespaces();
- for (int i = nestedNamespaces.size() - 1; i >= 0; --i) {
+ for (auto i = nestedNamespaces.size() - 1; i >= 0; --i) {
if (!hasMembers(nestedNamespaces.at(i)))
nestedNamespaces.removeAt(i);
}
@@ -132,7 +135,7 @@ static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceM
if (optJoinNamespaces) {
// Write out members of identical namespaces and remove
const QString name = current->name();
- for (int i = 0; i < nestedNamespaces.size(); ) {
+ for (qsizetype i = 0; i < nestedNamespaces.size(); ) {
if (nestedNamespaces.at(i)->name() == name) {
formatXmlNamespaceMembers(writer, nestedNamespaces.at(i));
nestedNamespaces.removeAt(i);
@@ -147,8 +150,8 @@ static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceM
for (const auto &func : nsp->functions()) {
const QString signature = func->typeSystemSignature();
if (!signature.contains(u"operator")) { // Skip free operators
- writer.writeStartElement(QStringLiteral("function"));
- writer.writeAttribute(QStringLiteral("signature"), signature);
+ writer.writeStartElement(u"function"_s);
+ writer.writeAttribute(u"signature"_s, signature);
writer.writeEndElement();
}
}
@@ -161,13 +164,13 @@ static void formatXmlOutput(const FileModelItem &dom)
QXmlStreamWriter writer(&output);
writer.setAutoFormatting(true);
writer.writeStartDocument();
- writer.writeStartElement(QStringLiteral("typesystem"));
- writer.writeAttribute(QStringLiteral("package"), QStringLiteral("insert_name"));
- writer.writeComment(QStringLiteral("Auto-generated ") +
+ writer.writeStartElement(u"typesystem"_s);
+ writer.writeAttribute(u"package"_s, u"insert_name"_s);
+ writer.writeComment(u"Auto-generated "_s +
QDateTime::currentDateTime().toString(Qt::ISODate));
for (auto p : primitiveTypes) {
- writer.writeStartElement(QStringLiteral("primitive-type"));
- writer.writeAttribute(nameAttribute(), QLatin1String(p));
+ writer.writeStartElement(u"primitive-type"_s);
+ writer.writeAttribute(nameAttribute, QLatin1StringView(p));
writer.writeEndElement();
}
formatXmlNamespaceMembers(writer, dom);
@@ -195,29 +198,29 @@ int main(int argc, char **argv)
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
const QString description =
- QString::fromLatin1(descriptionFormat).arg(QLatin1String(qVersion()),
+ QString::fromLatin1(descriptionFormat).arg(QLatin1StringView(qVersion()),
clang::libClangVersion().toString());
parser.setApplicationDescription(description);
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption verboseOption(QStringLiteral("verbose"),
- QStringLiteral("Display verbose output about types"));
+ QCommandLineOption verboseOption(u"verbose"_s,
+ u"Display verbose output about types"_s);
parser.addOption(verboseOption);
- QCommandLineOption debugOption(QStringLiteral("debug"),
- QStringLiteral("Display debug output"));
+ QCommandLineOption debugOption(u"debug"_s,
+ u"Display debug output"_s);
parser.addOption(debugOption);
- QCommandLineOption joinNamespacesOption({QStringLiteral("j"), QStringLiteral("join-namespaces")},
- QStringLiteral("Join namespaces"));
+ QCommandLineOption joinNamespacesOption({u"j"_s, u"join-namespaces"_s},
+ u"Join namespaces"_s);
parser.addOption(joinNamespacesOption);
- QCommandLineOption languageLevelOption(QStringLiteral("std"),
+ QCommandLineOption languageLevelOption(u"std"_s,
languageLevelDescription(),
- QStringLiteral("level"));
+ u"level"_s);
parser.addOption(languageLevelOption);
- parser.addPositionalArgument(QStringLiteral("argument"),
- QStringLiteral("C++ compiler argument"),
- QStringLiteral("argument(s)"));
+ parser.addPositionalArgument(u"argument"_s,
+ u"C++ compiler argument"_s,
+ u"argument(s)"_s);
parser.process(app);
const QStringList &positionalArguments = parser.positionalArguments();
@@ -242,8 +245,8 @@ int main(int argc, char **argv)
optJoinNamespaces = parser.isSet(joinNamespacesOption);
const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, true, level, 0);
- if (dom.isNull()) {
- QString message = QLatin1String("Unable to parse ") + positionalArguments.join(u' ');
+ if (!dom) {
+ QString message = u"Unable to parse "_s + positionalArguments.join(u' ');
std::cerr << qPrintable(message) << '\n';
return -2;
}
diff --git a/sources/shiboken6/tests/libminimal/CMakeLists.txt b/sources/shiboken6/tests/libminimal/CMakeLists.txt
index f906bdb84..4a10f96bf 100644
--- a/sources/shiboken6/tests/libminimal/CMakeLists.txt
+++ b/sources/shiboken6/tests/libminimal/CMakeLists.txt
@@ -1,9 +1,17 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(libminimal)
set(libminimal_SRC
-obj.cpp
-listuser.cpp
-typedef.cpp
+containeruser.cpp containeruser.h
+libminimalmacros.h
+listuser.cpp listuser.h
+minbool.h
+obj.cpp obj.h
+spanuser.cpp spanuser.h
+typedef.cpp typedef.h
+val.h
)
add_library(libminimal SHARED ${libminimal_SRC})
diff --git a/sources/shiboken6/tests/libminimal/containeruser.cpp b/sources/shiboken6/tests/libminimal/containeruser.cpp
new file mode 100644
index 000000000..29af52aef
--- /dev/null
+++ b/sources/shiboken6/tests/libminimal/containeruser.cpp
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "containeruser.h"
+
+#include <algorithm>
+#include <numeric>
+
+ContainerUser::ContainerUser() : m_intVector{1, 2, 3}, m_intArray{1, 2, 3}
+{
+}
+
+ContainerUser::~ContainerUser() = default;
+
+std::vector<int> ContainerUser::createIntVector(int num)
+{
+ std::vector<int> retval(num);
+ std::iota(retval.begin(), retval.end(), 0);
+ return retval;
+}
+
+int ContainerUser::sumIntVector(const std::vector<int> &intVector)
+{
+ return std::accumulate(intVector.cbegin(), intVector.cend(), 0);
+}
+
+std::vector<int> &ContainerUser::intVector()
+{
+ return m_intVector;
+}
+
+void ContainerUser::setIntVector(const std::vector<int> &v)
+{
+ m_intVector = v;
+}
+
+std::array<int, 3> ContainerUser::createIntArray()
+{
+ return {1, 2, 3};
+}
+
+int ContainerUser::sumIntArray(const std::array<int, 3> &intArray)
+{
+ return std::accumulate(intArray.cbegin(), intArray.cend(), 0);
+}
+
+std::array<int, 3> &ContainerUser::intArray()
+{
+ return m_intArray;
+}
+
+void ContainerUser::setIntArray(const std::array<int, 3> &a)
+{
+ m_intArray = a;
+}
diff --git a/sources/shiboken6/tests/libminimal/containeruser.h b/sources/shiboken6/tests/libminimal/containeruser.h
new file mode 100644
index 000000000..55e4020ec
--- /dev/null
+++ b/sources/shiboken6/tests/libminimal/containeruser.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CONTAINERUSER_H
+#define CONTAINERUSER_H
+
+#include "libminimalmacros.h"
+
+#include <array>
+#include <vector>
+
+/// Exercise simple, sequential containers. More advanced tests are in ListUser
+class LIBMINIMAL_API ContainerUser
+{
+public:
+ ContainerUser();
+ ~ContainerUser();
+
+ static std::vector<int> createIntVector(int num);
+ static int sumIntVector(const std::vector<int> &intVector);
+
+ std::vector<int> &intVector();
+ void setIntVector(const std::vector<int> &);
+
+ static std::array<int, 3> createIntArray();
+ static int sumIntArray(const std::array<int, 3> &intArray);
+
+ std::array<int, 3> &intArray();
+ void setIntArray(const std::array<int, 3> &);
+
+private:
+ std::vector<int> m_intVector;
+ std::array<int, 3> m_intArray;
+};
+
+#endif // CONTAINERUSER_H
diff --git a/sources/shiboken6/tests/libminimal/libminimalmacros.h b/sources/shiboken6/tests/libminimal/libminimalmacros.h
index e0dfdd196..099c1f1de 100644
--- a/sources/shiboken6/tests/libminimal/libminimalmacros.h
+++ b/sources/shiboken6/tests/libminimal/libminimalmacros.h
@@ -22,4 +22,28 @@
# define LIBMINIMAL_API LIBMINIMAL_IMPORT
#endif
+#define LIBMINIMAL_DEFAULT_COPY(Class) \
+ Class(const Class &) noexcept = default; \
+ Class &operator=(const Class &) noexcept = default;
+
+#define LIBMINIMAL_DISABLE_COPY(Class) \
+ Class(const Class &) = delete;\
+ Class &operator=(const Class &) = delete;
+
+#define LIBMINIMAL_DEFAULT_MOVE(Class) \
+ Class(Class &&) noexcept = default; \
+ Class &operator=(Class &&) noexcept = default;
+
+#define LIBMINIMAL_DEFAULT_COPY_MOVE(Class) \
+ LIBMINIMAL_DEFAULT_COPY(Class) \
+ LIBMINIMAL_DEFAULT_MOVE(Class)
+
+#define LIBMINIMAL_DISABLE_MOVE(Class) \
+ Class(Class &&) = delete; \
+ Class &operator=(Class &&) = delete;
+
+#define LIBMINIMAL_DISABLE_COPY_MOVE(Class) \
+ LIBMINIMAL_DISABLE_COPY(Class) \
+ LIBMINIMAL_DISABLE_MOVE(Class)
+
#endif // LIBMINIMALMACROS_H
diff --git a/sources/shiboken6/tests/libminimal/listuser.cpp b/sources/shiboken6/tests/libminimal/listuser.cpp
index 14ac1c7ee..93c399542 100644
--- a/sources/shiboken6/tests/libminimal/listuser.cpp
+++ b/sources/shiboken6/tests/libminimal/listuser.cpp
@@ -1,29 +1,35 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <numeric>
-#include <cstdlib>
#include "listuser.h"
#include <algorithm>
+#include <cstdlib>
#include <numeric>
-std::list<int>
-ListUser::createIntList(int num)
+std::list<int> ListUser::createIntList(int num)
{
std::list<int> retval(num);
std::iota(retval.begin(), retval.end(), 0);
return retval;
}
-int
-ListUser::sumIntList(std::list<int> intList)
+int ListUser::sumIntList(std::list<int> intList)
{
return std::accumulate(intList.begin(), intList.end(), 0);
}
-std::list<MinBool>
-ListUser::createMinBoolList(MinBool mb1, MinBool mb2)
+int ListUser::sumIntListDefaultParamConstRef(const std::list<int> &intList)
+{
+ return sumIntList(intList);
+}
+
+int ListUser::sumIntListDefaultParam(std::list<int> intList)
+{
+ return sumIntList(intList);
+}
+
+std::list<MinBool> ListUser::createMinBoolList(MinBool mb1, MinBool mb2)
{
std::list<MinBool> retval;
retval.push_back(mb1);
@@ -31,8 +37,7 @@ ListUser::createMinBoolList(MinBool mb1, MinBool mb2)
return retval;
}
-MinBool
-ListUser::oredMinBoolList(std::list<MinBool> minBoolList)
+MinBool ListUser::oredMinBoolList(std::list<MinBool> minBoolList)
{
MinBool result(false);
for (const auto &m : minBoolList)
@@ -40,8 +45,7 @@ ListUser::oredMinBoolList(std::list<MinBool> minBoolList)
return result;
}
-std::list<Val>
-ListUser::createValList(int num)
+std::list<Val> ListUser::createValList(int num)
{
std::list<Val> retval;
for (int i = 0; i < num; ++i)
@@ -49,17 +53,14 @@ ListUser::createValList(int num)
return retval;
}
-int
-ListUser::sumValList(std::list<Val> valList)
+int ListUser::sumValList(std::list<Val> valList)
{
int total = 0;
for (const auto &v : valList)
total += v.valId();
return total;
}
-
-std::list<Obj*>
-ListUser::createObjList(Obj* o1, Obj* o2)
+std::list<Obj*> ListUser::createObjList(Obj* o1, Obj* o2)
{
std::list<Obj*> retval;
retval.push_back(o1);
@@ -67,8 +68,7 @@ ListUser::createObjList(Obj* o1, Obj* o2)
return retval;
}
-int
-ListUser::sumObjList(std::list<Obj*> objList)
+int ListUser::sumObjList(std::list<Obj*> objList)
{
int total = 0;
for (const auto *obj : objList)
@@ -76,8 +76,7 @@ ListUser::sumObjList(std::list<Obj*> objList)
return total;
}
-std::list<std::list<int> >
-ListUser::createListOfIntLists(int num)
+std::list<std::list<int> > ListUser::createListOfIntLists(int num)
{
std::list<std::list<int> > retval;
for (int i = 0; i < num; ++i)
@@ -85,8 +84,7 @@ ListUser::createListOfIntLists(int num)
return retval;
}
-int
-ListUser::sumListOfIntLists(std::list<std::list<int> > intListList)
+int ListUser::sumListOfIntLists(std::list<std::list<int> > intListList)
{
int total = 0;
for (const auto &list : intListList)
diff --git a/sources/shiboken6/tests/libminimal/listuser.h b/sources/shiboken6/tests/libminimal/listuser.h
index 2254cb138..9904ef27d 100644
--- a/sources/shiboken6/tests/libminimal/listuser.h
+++ b/sources/shiboken6/tests/libminimal/listuser.h
@@ -4,16 +4,21 @@
#ifndef LISTUSER_H
#define LISTUSER_H
-#include <list>
#include "obj.h"
#include "val.h"
#include "minbool.h"
#include "libminimalmacros.h"
+#include <list>
+
struct LIBMINIMAL_API ListUser
{
- virtual ~ListUser() {}
+ LIBMINIMAL_DEFAULT_COPY(ListUser)
+ LIBMINIMAL_DISABLE_MOVE(ListUser)
+
+ ListUser() noexcept = default;
+ virtual ~ListUser() = default;
// List of C++ primitive type items
virtual std::list<int> createIntList(int num);
@@ -21,6 +26,9 @@ struct LIBMINIMAL_API ListUser
virtual int sumIntList(std::list<int> intList);
int callSumIntList(std::list<int> intList) { return sumIntList(intList); }
+ int sumIntListDefaultParamConstRef(const std::list<int> &intList = {1, 2, 3});
+ int sumIntListDefaultParam(std::list<int> intList = {1, 2, 3});
+
// List of C++ MinBool objects used as primitives in Python
virtual std::list<MinBool> createMinBoolList(MinBool mb1, MinBool mb2);
std::list<MinBool> callCreateMinBoolList(MinBool mb1, MinBool mb2) { return createMinBoolList(mb1, mb2); }
diff --git a/sources/shiboken6/tests/libminimal/minbool.h b/sources/shiboken6/tests/libminimal/minbool.h
index f75e458da..e460f466b 100644
--- a/sources/shiboken6/tests/libminimal/minbool.h
+++ b/sources/shiboken6/tests/libminimal/minbool.h
@@ -13,9 +13,10 @@ public:
bool value() const { return m_value; }
inline MinBool operator!() const { return MinBool(!m_value); }
inline MinBool& operator|=(const MinBool& other) {
- m_value = m_value | other.m_value;
+ m_value |= other.m_value;
return *this;
}
+
private:
bool m_value;
};
@@ -30,12 +31,16 @@ inline bool operator!=(MinBool b1, MinBool b2) { return (!b1).value() != (!b2).v
class LIBMINIMAL_API MinBoolUser
{
public:
- MinBoolUser() : m_minbool(MinBool(false)) {}
- virtual ~MinBoolUser() {}
+ LIBMINIMAL_DEFAULT_COPY(MinBoolUser)
+ LIBMINIMAL_DISABLE_MOVE(MinBoolUser)
+
+ MinBoolUser() noexcept : m_minbool(MinBool(false)) {}
+ virtual ~MinBoolUser() = default;
inline MinBool minBool() { return m_minbool; }
inline void setMinBool(MinBool minBool) { m_minbool = minBool; }
virtual MinBool invertedMinBool() { return !m_minbool; }
inline MinBool callInvertedMinBool() { return invertedMinBool(); }
+
private:
MinBool m_minbool;
};
diff --git a/sources/shiboken6/tests/libminimal/obj.cpp b/sources/shiboken6/tests/libminimal/obj.cpp
index 0e49fee8b..a63a9c3c9 100644
--- a/sources/shiboken6/tests/libminimal/obj.cpp
+++ b/sources/shiboken6/tests/libminimal/obj.cpp
@@ -3,14 +3,13 @@
#include "obj.h"
-Obj::Obj(int objId) : m_objId(objId)
+Obj::Obj(int objId) noexcept : m_objId(objId)
{
}
Obj::~Obj() = default;
-bool
-Obj::virtualMethod(int val)
+bool Obj::virtualMethod(int val)
{
return !bool(val%2);
}
diff --git a/sources/shiboken6/tests/libminimal/obj.h b/sources/shiboken6/tests/libminimal/obj.h
index 55a798c02..be0bfb52b 100644
--- a/sources/shiboken6/tests/libminimal/obj.h
+++ b/sources/shiboken6/tests/libminimal/obj.h
@@ -9,7 +9,9 @@
class LIBMINIMAL_API Obj
{
public:
- explicit Obj(int objId);
+ LIBMINIMAL_DISABLE_COPY_MOVE(Obj)
+
+ explicit Obj(int objId) noexcept;
virtual ~Obj();
int objId() const { return m_objId; }
@@ -25,8 +27,6 @@ public:
Obj* callPassObjectTypeReference(Obj& obj) { return passObjectTypeReference(obj); }
private:
- Obj(const Obj&);
- Obj& operator=(const Obj&);
int m_objId;
};
diff --git a/sources/shiboken6/tests/libminimal/spanuser.cpp b/sources/shiboken6/tests/libminimal/spanuser.cpp
new file mode 100644
index 000000000..fea9cd68e
--- /dev/null
+++ b/sources/shiboken6/tests/libminimal/spanuser.cpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "spanuser.h"
+
+#include <numeric>
+
+SpanUser::SpanUser() = default;
+
+bool SpanUser::enabled()
+{
+#if __cplusplus >= 202002L
+ return true;
+#else
+ return false;
+#endif
+}
+
+#if __cplusplus >= 202002L
+IntSpan3 SpanUser::getIntSpan3()
+{
+ static int iv[] = {1, 2, 3};
+ return IntSpan3(iv);
+}
+
+IntSpan SpanUser::getIntSpan()
+{
+ static int iv[] = {1, 2, 3};
+ return IntSpan(iv);
+}
+
+ConstIntSpan3 SpanUser::getConstIntSpan3()
+{
+ static const int civ[] = {1, 2, 3};
+ return ConstIntSpan3(civ);
+}
+
+IntSpan3 SpanUser::getIntSpan3_OpaqueContainer()
+{
+ static int iv[] = {1, 2, 3};
+ return IntSpan3(iv);
+}
+
+int SpanUser::sumIntSpan3(IntSpan3 isp3)
+{
+ return std::accumulate(isp3.begin(), isp3.end(), 0);
+}
+
+int SpanUser::sumIntSpan(IntSpan isp)
+{
+ return std::accumulate(isp.begin(), isp.end(), 0);
+}
+
+int SpanUser::sumConstIntSpan3(ConstIntSpan3 ispc3)
+{
+ return std::accumulate(ispc3.begin(), ispc3.end(), 0);
+}
+#endif // C++ 20
diff --git a/sources/shiboken6/tests/libminimal/spanuser.h b/sources/shiboken6/tests/libminimal/spanuser.h
new file mode 100644
index 000000000..c78ba35e7
--- /dev/null
+++ b/sources/shiboken6/tests/libminimal/spanuser.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef SPANUSER_H
+#define SPANUSER_H
+
+#include "libminimalmacros.h"
+
+#if __cplusplus >= 202002L
+# include <span>
+
+using IntSpan3 = std::span<int, 3>;
+using IntSpan = std::span<int>;
+using ConstIntSpan3 = std::span<const int, 3>;
+#endif
+
+struct LIBMINIMAL_API SpanUser
+{
+ SpanUser();
+
+ static bool enabled();
+
+#if __cplusplus >= 202002L
+ static IntSpan3 getIntSpan3();
+ static IntSpan getIntSpan();
+ static ConstIntSpan3 getConstIntSpan3();
+ static IntSpan3 getIntSpan3_OpaqueContainer();
+
+ static int sumIntSpan3(IntSpan3 isp3);
+ static int sumIntSpan(IntSpan isp);
+ static int sumConstIntSpan3(ConstIntSpan3 ispc3);
+#endif // C++ 20
+};
+
+#endif // SPANUSER_H
diff --git a/sources/shiboken6/tests/libminimal/val.h b/sources/shiboken6/tests/libminimal/val.h
index af53263bd..50f090a7d 100644
--- a/sources/shiboken6/tests/libminimal/val.h
+++ b/sources/shiboken6/tests/libminimal/val.h
@@ -9,8 +9,10 @@
class LIBMINIMAL_API Val
{
public:
- explicit Val(int valId) : m_valId(valId) {}
- virtual ~Val() {}
+ explicit Val(int valId) noexcept : m_valId(valId) {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Val)
+
+ virtual ~Val() = default;
int valId() const { return m_valId; }
void setValId(int valId) { m_valId = valId; }
diff --git a/sources/shiboken6/tests/libother/CMakeLists.txt b/sources/shiboken6/tests/libother/CMakeLists.txt
index c078d3546..0379d740b 100644
--- a/sources/shiboken6/tests/libother/CMakeLists.txt
+++ b/sources/shiboken6/tests/libother/CMakeLists.txt
@@ -1,12 +1,17 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(libother)
set(libother_SRC
-number.cpp
-otherderived.cpp
-otherobjecttype.cpp
-othermultiplederived.cpp
-smartptrtester.cpp
-othertypesystypedef.cpp
+extendsnoimplicitconversion.h
+libothermacros.h
+number.cpp number.h
+otherderived.cpp otherderived.h
+othermultiplederived.cpp othermultiplederived.h
+otherobjecttype.cpp otherobjecttype.h
+othertypesystypedef.cpp othertypesystypedef.h
+smartptrtester.cpp smartptrtester.h
)
add_library(libother SHARED ${libother_SRC})
diff --git a/sources/shiboken6/tests/libother/extendsnoimplicitconversion.h b/sources/shiboken6/tests/libother/extendsnoimplicitconversion.h
index bf6cd736c..36d503fe8 100644
--- a/sources/shiboken6/tests/libother/extendsnoimplicitconversion.h
+++ b/sources/shiboken6/tests/libother/extendsnoimplicitconversion.h
@@ -13,8 +13,9 @@ public:
explicit ExtendsNoImplicitConversion(int objId) : m_objId(objId) {};
inline int objId() const { return m_objId; }
inline operator NoImplicitConversion() const { return NoImplicitConversion(m_objId); }
+
private:
int m_objId;
};
-#endif // EXTENDSNOIMPLICITCONVERSION_H
+#endif // EXTENDSNOIMPLICITCONVERSION_H
diff --git a/sources/shiboken6/tests/libother/number.cpp b/sources/shiboken6/tests/libother/number.cpp
index c21c7c086..fbf50dc4a 100644
--- a/sources/shiboken6/tests/libother/number.cpp
+++ b/sources/shiboken6/tests/libother/number.cpp
@@ -2,33 +2,27 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "number.h"
-#include <cstring>
-#include <sstream>
-using namespace std;
+#include <sstream>
-Str
-Number::toStr() const
+Str Number::toStr() const
{
- ostringstream in;
+ std::ostringstream in;
in << m_value;
return in.str().c_str();
}
-Point
-operator*(const Point& p, const Number& n)
+Point operator*(const Point &p, const Number &n)
{
- return Point(p.x() * n.value(), p.y() * n.value());
+ return {p.x() * n.value(), p.y() * n.value()};
}
-Complex
-Number::toComplex() const
+Complex Number::toComplex() const
{
return Complex(m_value);
}
-Number
-Number::fromComplex(Complex cpx)
+Number Number::fromComplex(Complex cpx)
{
return Number(cpx.real());
}
diff --git a/sources/shiboken6/tests/libother/number.h b/sources/shiboken6/tests/libother/number.h
index 85f888d82..2c480e7f2 100644
--- a/sources/shiboken6/tests/libother/number.h
+++ b/sources/shiboken6/tests/libother/number.h
@@ -18,7 +18,7 @@ public:
Str toStr() const;
inline operator Str() const { return toStr(); }
- friend LIBOTHER_API Point operator*(const Point&, const Number&);
+ friend LIBOTHER_API Point operator*(const Point &, const Number &);
Complex toComplex() const;
static Number fromComplex(Complex cpx);
@@ -27,6 +27,6 @@ private:
int m_value;
};
-LIBOTHER_API Point operator*(const Point&, const Number&);
+LIBOTHER_API Point operator*(const Point &, const Number &);
#endif // NUMBER_H
diff --git a/sources/shiboken6/tests/libother/otherderived.cpp b/sources/shiboken6/tests/libother/otherderived.cpp
index 12521b73c..93a18876e 100644
--- a/sources/shiboken6/tests/libother/otherderived.cpp
+++ b/sources/shiboken6/tests/libother/otherderived.cpp
@@ -7,30 +7,24 @@ OtherDerived::OtherDerived(int id) : Abstract(id)
{
}
-OtherDerived::~OtherDerived()
-{
-}
+OtherDerived::~OtherDerived() = default;
-Abstract*
-OtherDerived::createObject()
+Abstract *OtherDerived::createObject()
{
static int id = 100;
return new OtherDerived(id++);
}
-void
-OtherDerived::pureVirtual()
+void OtherDerived::pureVirtual()
{
}
-void*
-OtherDerived::pureVirtualReturningVoidPtr()
+void *OtherDerived::pureVirtualReturningVoidPtr()
{
return nullptr;
}
-void
-OtherDerived::unpureVirtual()
+void OtherDerived::unpureVirtual()
{
}
diff --git a/sources/shiboken6/tests/libother/otherderived.h b/sources/shiboken6/tests/libother/otherderived.h
index cefb4dc11..d6bde8808 100644
--- a/sources/shiboken6/tests/libother/otherderived.h
+++ b/sources/shiboken6/tests/libother/otherderived.h
@@ -18,26 +18,26 @@ public:
OtherDerived(int id = -1);
~OtherDerived() override;
void pureVirtual() override;
- void* pureVirtualReturningVoidPtr() override;
+ void *pureVirtualReturningVoidPtr() override;
void unpureVirtual() override;
PrintFormat returnAnEnum() override { return Short; }
- inline void useObjectTypeFromOtherModule(ObjectType*) {}
- inline Event useValueTypeFromOtherModule(const Event& e) { return e; }
- inline Complex useValueTypeFromOtherModule(const Complex& c) { return c; }
+ inline void useObjectTypeFromOtherModule(ObjectType *) {}
+ inline Event useValueTypeFromOtherModule(const Event &e) { return e; }
+ inline Complex useValueTypeFromOtherModule(const Complex &c) { return c; }
inline void useEnumTypeFromOtherModule(OverloadedFuncEnum) {}
// factory method
- static Abstract* createObject();
+ static Abstract *createObject();
void hideFunction(HideType*) override {}
protected:
- inline const char* getClassName() { return className(); }
- virtual const char* className() override { return "OtherDerived"; }
+ inline const char *getClassName() { return className(); }
+ const char *className() const override { return "OtherDerived"; }
private:
void pureVirtualPrivate() override;
};
-#endif // OTHERDERIVED_H
+#endif // OTHERDERIVED_H
diff --git a/sources/shiboken6/tests/libother/othermultiplederived.cpp b/sources/shiboken6/tests/libother/othermultiplederived.cpp
index 41718fc49..cfbbfb2c2 100644
--- a/sources/shiboken6/tests/libother/othermultiplederived.cpp
+++ b/sources/shiboken6/tests/libother/othermultiplederived.cpp
@@ -8,18 +8,17 @@ VirtualMethods OtherMultipleDerived::returnUselessClass()
return VirtualMethods();
}
-Base1* OtherMultipleDerived::createObject(const std::string& objName)
+Base1 *OtherMultipleDerived::createObject(const std::string &objName)
{
if (objName == "Base1")
return new Base1;
- else if (objName == "MDerived1")
+ if (objName == "MDerived1")
return new MDerived1;
- else if (objName == "SonOfMDerived1")
+ if (objName == "SonOfMDerived1")
return new SonOfMDerived1;
- else if (objName == "MDerived3")
+ if (objName == "MDerived3")
return new MDerived3;
- else if (objName == "OtherMultipleDerived")
+ if (objName == "OtherMultipleDerived")
return new OtherMultipleDerived;
return nullptr;
}
-
diff --git a/sources/shiboken6/tests/libother/othermultiplederived.h b/sources/shiboken6/tests/libother/othermultiplederived.h
index c209c72ac..cd9910687 100644
--- a/sources/shiboken6/tests/libother/othermultiplederived.h
+++ b/sources/shiboken6/tests/libother/othermultiplederived.h
@@ -10,12 +10,12 @@
class ObjectType;
-class LIBOTHER_API OtherMultipleDerived : public MDerived1
+class LIBOTHER_API OtherMultipleDerived : public OtherBase, public MDerived1
{
public:
// this will use CppCopier from other module (bug#142)
VirtualMethods returnUselessClass();
- static Base1* createObject(const std::string& objName);
+ static Base1 *createObject(const std::string &objName);
};
-#endif
+#endif // OTHERMULTIPLEDERIVED_H
diff --git a/sources/shiboken6/tests/libother/otherobjecttype.cpp b/sources/shiboken6/tests/libother/otherobjecttype.cpp
index fee6f5bfa..eaaa231be 100644
--- a/sources/shiboken6/tests/libother/otherobjecttype.cpp
+++ b/sources/shiboken6/tests/libother/otherobjecttype.cpp
@@ -3,10 +3,9 @@
#include "otherobjecttype.h"
-Collector&
-operator<<(Collector& collector, const OtherObjectType& obj)
+Collector &operator<<(Collector &collector, const OtherObjectType &obj)
{
- collector << obj.identifier()*2;
+ collector << obj.identifier() * 2;
return collector;
}
diff --git a/sources/shiboken6/tests/libother/otherobjecttype.h b/sources/shiboken6/tests/libother/otherobjecttype.h
index b301ce22b..844795118 100644
--- a/sources/shiboken6/tests/libother/otherobjecttype.h
+++ b/sources/shiboken6/tests/libother/otherobjecttype.h
@@ -4,16 +4,12 @@
#ifndef OTHEROBJECTTYPE_H
#define OTHEROBJECTTYPE_H
-#include <list>
-#include "str.h"
-
#include "libothermacros.h"
#include "objecttype.h"
#include "collector.h"
#include "samplenamespace.h"
#include "removednamespaces.h"
-
class LIBOTHER_API OtherObjectType : public ObjectType
{
public:
@@ -21,8 +17,6 @@ public:
static int enumAsIntForInvisibleNamespace(RemovedNamespace1::RemovedNamespace1_Enum value);
};
-
-LIBOTHER_API Collector& operator<<(Collector&, const OtherObjectType&);
+LIBOTHER_API Collector &operator<<(Collector &, const OtherObjectType &);
#endif // OTHEROBJECTTYPE_H
-
diff --git a/sources/shiboken6/tests/libother/smartptrtester.cpp b/sources/shiboken6/tests/libother/smartptrtester.cpp
index 25b6a406e..1c6496b1a 100644
--- a/sources/shiboken6/tests/libother/smartptrtester.cpp
+++ b/sources/shiboken6/tests/libother/smartptrtester.cpp
@@ -5,7 +5,7 @@
SharedPtr<Str> SmartPtrTester::createSharedPtrStr(const char *what)
{
- return SharedPtr<Str>(new Str(what));
+ return {new Str(what)};
}
std::string SmartPtrTester::valueOfSharedPtrStr(const SharedPtr<Str> &str)
diff --git a/sources/shiboken6/tests/libsample/CMakeLists.txt b/sources/shiboken6/tests/libsample/CMakeLists.txt
index 6e436ee1f..926972340 100644
--- a/sources/shiboken6/tests/libsample/CMakeLists.txt
+++ b/sources/shiboken6/tests/libsample/CMakeLists.txt
@@ -1,63 +1,93 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(libsample)
set(libsample_SRC
-abstract.cpp
-blackbox.cpp
-bytearray.cpp
-bucket.cpp
-collector.cpp
-complex.cpp
-ctparam.cpp
-onlycopy.cpp
-derived.cpp
-derivedusingct.cpp
-echo.cpp
-exceptiontest.cpp
-functions.cpp
-handle.cpp
-implicitconv.cpp
-intwrapper.cpp
-injectcode.cpp
-listuser.cpp
-modifications.cpp
-mapuser.cpp
-modified_constructor.cpp
-multiple_derived.cpp
-oddbool.cpp
-objectmodel.cpp
-objecttype.cpp
-objecttypeholder.cpp
-objecttypelayout.cpp
-objecttypeoperators.cpp
-objectview.cpp
-overload.cpp
-overloadsort.cpp
-pairuser.cpp
-pen.cpp
-photon.cpp
-point.cpp
-pointf.cpp
-polygon.cpp
-protected.cpp
-reference.cpp
-renaming.cpp
-sample.cpp
-samplenamespace.cpp
-sbkdate.cpp
-simplefile.cpp
-size.cpp
-snakecasetest.cpp
-sometime.cpp
-str.cpp
-strlist.cpp
-templateptr.cpp
-transform.cpp
-typesystypedef.cpp
-virtualmethods.cpp
-expression.cpp
-filter.cpp
+abstract.cpp abstract.h
+blackbox.cpp blackbox.h
+bucket.cpp bucket.h
+bytearray.cpp bytearray.h
+collector.cpp collector.h
+complex.cpp complex.h
+ctorconvrule.h
+ctparam.cpp ctparam.h
+cvlist.h
+derived.cpp derived.h
+derivedusingct.cpp derivedusingct.h
+echo.cpp echo.h
+exceptiontest.cpp exceptiontest.h
+expression.cpp expression.h
+filter.cpp filter.h
+functions.cpp functions.h
+handle.cpp handle.h
+implicitconv.cpp implicitconv.h
+injectcode.cpp injectcode.h
+intwrapper.cpp intwrapper.h
+libsamplemacros.h
+list.h
+listuser.cpp listuser.h
+mapuser.cpp mapuser.h
+modelindex.h
+modifications.cpp modifications.h
+modified_constructor.cpp modified_constructor.h
+multiple_derived.cpp multiple_derived.h
+noimplicitconversion.h
+nondefaultctor.h
+nontypetemplate.h
+null.h
+objectmodel.cpp objectmodel.h
+objecttype.cpp objecttype.h
+objecttypebyvalue.h
+objecttypeholder.cpp objecttypeholder.h
+objecttypelayout.cpp objecttypelayout.h
+objecttypeoperators.cpp objecttypeoperators.h
+objectview.cpp objectview.h
+oddbool.cpp oddbool.h
+onlycopy.cpp onlycopy.h
+overload.cpp overload.h
+overloadsort.cpp overloadsort.h
+pairuser.cpp pairuser.h
+pen.cpp pen.h
+photon.cpp photon.h
+point.cpp point.h
+pointerholder.h
+pointf.cpp pointf.h
+polygon.cpp polygon.h
+privatector.h
+privatedtor.h
+protected.cpp protected.h
+rect.h
+reference.cpp reference.h
+removednamespaces.h
+renaming.cpp renaming.h
+sample.cpp sample.h
+samplenamespace.cpp samplenamespace.h
+sbkdate.cpp sbkdate.h
+stdcomplex.cpp stdcomplex.h
+simplefile.cpp simplefile.h
+size.cpp size.h
+snakecasetest.cpp snakecasetest.h
+sometime.cpp sometime.h
+str.cpp str.h
+strlist.cpp strlist.h
+templateptr.cpp templateptr.h
+transform.cpp transform.h
+typesystypedef.cpp typesystypedef.h
+valueandvirtual.h
+virtualmethods.cpp virtualmethods.h
+voidholder.h
)
+# Includes windows.h which is causing clashes between class Polygon and
+# wingdi.h's Polygon() function.
+
+if(WIN32)
+ set_source_files_properties(
+ bucket.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON
+ )
+endif()
+
add_library(libsample SHARED ${libsample_SRC})
target_include_directories(libsample PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(libsample PRIVATE LIBSAMPLE_BUILD)
diff --git a/sources/shiboken6/tests/libsample/abstract.cpp b/sources/shiboken6/tests/libsample/abstract.cpp
index 65fd651ad..0d67d8630 100644
--- a/sources/shiboken6/tests/libsample/abstract.cpp
+++ b/sources/shiboken6/tests/libsample/abstract.cpp
@@ -1,64 +1,64 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "abstract.h"
-#include "objecttype.h"
-using namespace std;
+#include <iostream>
const int Abstract::staticPrimitiveField = 0;
-Abstract::Abstract(int id) : m_id(id)
+Abstract::Abstract(int id) noexcept : m_id(id)
{
- toBeRenamedField = readOnlyField = primitiveField = 123;
- valueTypeField = Point(12, 34);
- objectTypeField = nullptr;
bitField = 0;
}
-Abstract::~Abstract()
-{
-}
+Abstract::~Abstract() = default;
-void
-Abstract::unpureVirtual()
+void Abstract::unpureVirtual()
{
}
-void
-Abstract::callUnpureVirtual()
+void Abstract::callUnpureVirtual()
{
this->unpureVirtual();
}
-
-void
-Abstract::callPureVirtual()
+void Abstract::callPureVirtual()
{
this->pureVirtual();
}
-void
-Abstract::show(PrintFormat format)
+void Abstract::show(PrintFormat format) const
{
- cout << '<';
+ std::cout << '<';
switch(format) {
- case Short:
- cout << this;
- break;
- case Verbose:
- cout << "class " << className() << " | cptr: " << this;
- cout << ", id: " << m_id;
- break;
- case OnlyId:
- cout << "id: " << m_id;
- break;
- case ClassNameAndId:
- cout << className() << " - id: " << m_id;
- break;
+ case Short:
+ std::cout << this;
+ break;
+ case Verbose:
+ std::cout << "class " << className() << " | cptr: " << this
+ << ", id: " << m_id;
+ break;
+ case OnlyId:
+ std::cout << "id: " << m_id;
+ break;
+ case ClassNameAndId:
+ std::cout << className() << " - id: " << m_id;
+ break;
}
- cout << '>';
+ std::cout << '>';
+}
+
+void Abstract::virtualWithOutParameter(int &x) const
+{
+ x = 42;
+}
+
+int Abstract::callVirtualWithOutParameter() const
+{
+ int x;
+ virtualWithOutParameter(x);
+ return x;
}
void Abstract::callVirtualGettingEnum(PrintFormat p)
@@ -66,7 +66,6 @@ void Abstract::callVirtualGettingEnum(PrintFormat p)
virtualGettingAEnum(p);
}
-void Abstract::virtualGettingAEnum(Abstract::PrintFormat p)
+void Abstract::virtualGettingAEnum(Abstract::PrintFormat)
{
}
-
diff --git a/sources/shiboken6/tests/libsample/abstract.h b/sources/shiboken6/tests/libsample/abstract.h
index 0e66ad0e1..4c1b98d90 100644
--- a/sources/shiboken6/tests/libsample/abstract.h
+++ b/sources/shiboken6/tests/libsample/abstract.h
@@ -24,6 +24,8 @@ private:
PrivValue2 = PrivValue1 + 2
};
public:
+ LIBMINIMAL_DISABLE_COPY_MOVE(Abstract)
+
enum PrintFormat {
Short,
Verbose,
@@ -38,26 +40,26 @@ public:
};
static const int staticPrimitiveField;
- int primitiveField;
+ int primitiveField = 123;
Complex userPrimitiveField;
- Point valueTypeField;
- ObjectType* objectTypeField;
- int toBeRenamedField;
- int readOnlyField;
+ Point valueTypeField{12, 34};
+ ObjectType *objectTypeField = nullptr;
+ int toBeRenamedField = 123;
+ int readOnlyField = 123;
- Abstract(int id = -1);
+ explicit Abstract(int id = -1) noexcept;
virtual ~Abstract();
- inline int id() { return m_id; }
+ inline int id() const { return m_id; }
// factory method
- inline static Abstract* createObject() { return nullptr; }
+ inline static Abstract *createObject() { return nullptr; }
// method that receives an Object Type
- inline static int getObjectId(Abstract* obj) { return obj->id(); }
+ inline static int getObjectId(Abstract *obj) { return obj->id(); }
virtual void pureVirtual() = 0;
- virtual void* pureVirtualReturningVoidPtr() = 0;
+ virtual void *pureVirtualReturningVoidPtr() = 0;
virtual void unpureVirtual();
virtual PrintFormat returnAnEnum() = 0;
@@ -67,13 +69,16 @@ public:
void callPureVirtual();
void callUnpureVirtual();
- void show(PrintFormat format = Verbose);
+ void show(PrintFormat format = Verbose) const;
virtual Type type() const { return TpAbstract; }
- virtual void hideFunction(HideType* arg) = 0;
+ virtual void hideFunction(HideType *arg) = 0;
+
+ virtual void virtualWithOutParameter(int &x) const;
+ int callVirtualWithOutParameter() const;
protected:
- virtual const char* className() { return "Abstract"; }
+ virtual const char *className() const { return "Abstract"; }
// Protected bit-field structure member.
unsigned int bitField: 1;
@@ -82,4 +87,5 @@ private:
virtual void pureVirtualPrivate() = 0;
int m_id;
};
+
#endif // ABSTRACT_H
diff --git a/sources/shiboken6/tests/libsample/blackbox.cpp b/sources/shiboken6/tests/libsample/blackbox.cpp
index f648a3770..2ac435d3d 100644
--- a/sources/shiboken6/tests/libsample/blackbox.cpp
+++ b/sources/shiboken6/tests/libsample/blackbox.cpp
@@ -3,102 +3,79 @@
#include "blackbox.h"
-using namespace std;
-
BlackBox::~BlackBox()
{
// Free all maps.
- while (!m_objects.empty()) {
- delete (*m_objects.begin()).second;
- m_objects.erase(m_objects.begin());
- }
- while (!m_points.empty()) {
- delete (*m_points.begin()).second;
- m_points.erase(m_points.begin());
- }
+ for (const auto &p :m_objects)
+ delete p.second;
+ for (const auto &p : m_points)
+ delete p.second;
}
-int
-BlackBox::keepObjectType(ObjectType* object)
+int BlackBox::keepObjectType(ObjectType *object)
{
- m_ticket++;
- std::pair<int, ObjectType*> item(m_ticket, object);
- m_objects.insert(item);
+ ++m_ticket;
+ m_objects.insert({m_ticket, object});
object->setParent(nullptr);
return m_ticket;
}
-ObjectType*
-BlackBox::retrieveObjectType(int ticket)
+ObjectType *BlackBox::retrieveObjectType(int ticket)
{
const auto it = m_objects.find(ticket);
if (it != m_objects.end()) {
- ObjectType* second = it->second;
+ ObjectType *second = it->second;
m_objects.erase(it);
return second;
}
return nullptr;
}
-void
-BlackBox::disposeObjectType(int ticket)
+void BlackBox::disposeObjectType(int ticket)
{
- ObjectType* object = retrieveObjectType(ticket);
- if (object)
- delete object;
+ delete retrieveObjectType(ticket);
}
-int
-BlackBox::keepPoint(Point* point)
+int BlackBox::keepPoint(Point *point)
{
- m_ticket++;
- std::pair<int, Point*> item(m_ticket, point);
- m_points.insert(item);
-
+ ++m_ticket;
+ m_points.insert({m_ticket, point});
return m_ticket;
}
-Point*
-BlackBox::retrievePoint(int ticket)
+Point *BlackBox::retrievePoint(int ticket)
{
const auto it = m_points.find(ticket);
if (it != m_points.end()) {
- Point* second = it->second;
+ Point *second = it->second;
m_points.erase(it);
return second;
}
return nullptr;
}
-void
-BlackBox::disposePoint(int ticket)
+void BlackBox::disposePoint(int ticket)
{
- Point* point = retrievePoint(ticket);
- if (point)
- delete point;
+ delete retrievePoint(ticket);
}
-
-std::list<ObjectType*>
-BlackBox::objects()
+std::list<ObjectType*> BlackBox::objects()
{
std::list<ObjectType*> l;
- for (auto it = m_objects.begin(), end = m_objects.end(); it != end; ++it)
- l.push_back((*it).second);
+ for (const auto &p : m_objects)
+ l.push_back(p.second);
return l;
}
-std::list<Point*>
-BlackBox::points()
+std::list<Point*> BlackBox::points()
{
std::list<Point*> l;
- for (auto it = m_points.begin(), end = m_points.end(); it != end; ++it)
- l.push_back((*it).second);
+ for (const auto &p : m_points)
+ l.push_back(p.second);
return l;
}
-
diff --git a/sources/shiboken6/tests/libsample/blackbox.h b/sources/shiboken6/tests/libsample/blackbox.h
index bfcbd2128..9d32670dd 100644
--- a/sources/shiboken6/tests/libsample/blackbox.h
+++ b/sources/shiboken6/tests/libsample/blackbox.h
@@ -5,25 +5,28 @@
#define BLACKBOX_H
#include "libsamplemacros.h"
-#include <map>
#include "objecttype.h"
#include "point.h"
+#include <list>
+#include <map>
+
class LIBSAMPLE_API BlackBox
{
public:
- typedef std::map<int, ObjectType*> ObjectTypeMap;
- typedef std::map<int, Point*> PointMap;
+ using ObjectTypeMap = std::map<int, ObjectType*>;
+ using PointMap = std::map<int, Point*>;
- BlackBox() { m_ticket = -1;}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(BlackBox)
+ BlackBox() noexcept = default;
~BlackBox();
- int keepObjectType(ObjectType* object);
- ObjectType* retrieveObjectType(int ticket);
+ int keepObjectType(ObjectType *object);
+ ObjectType *retrieveObjectType(int ticket);
void disposeObjectType(int ticket);
- int keepPoint(Point* point);
- Point* retrievePoint(int ticket);
+ int keepPoint(Point *point);
+ Point *retrievePoint(int ticket);
void disposePoint(int ticket);
std::list<ObjectType*> objects();
@@ -35,8 +38,7 @@ public:
private:
ObjectTypeMap m_objects;
PointMap m_points;
- int m_ticket;
+ int m_ticket = -1;
};
#endif // BLACKBOX_H
-
diff --git a/sources/shiboken6/tests/libsample/bucket.cpp b/sources/shiboken6/tests/libsample/bucket.cpp
index 01a1f591e..cafd382a9 100644
--- a/sources/shiboken6/tests/libsample/bucket.cpp
+++ b/sources/shiboken6/tests/libsample/bucket.cpp
@@ -2,23 +2,20 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "bucket.h"
+
#include <iostream>
#ifdef _WIN32 // _WIN32 is defined by all Windows 32 and 64 bit compilers, but not by others.
-#include <windows.h>
-#define SLEEP(x) Sleep(x)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# define SLEEP(x) Sleep(x)
#else
-#include <unistd.h>
-#define SLEEP(x) usleep(x)
+# include <unistd.h>
+# define SLEEP(x) usleep(x)
#endif
-
-using namespace std;
-
-Bucket::Bucket() : m_locked(false)
-{
-}
-
void Bucket::push(int x)
{
m_data.push_back(x);
@@ -28,7 +25,7 @@ int Bucket::pop(void)
{
int x = 0;
- if (m_data.size() > 0) {
+ if (!m_data.empty()) {
x = m_data.front();
m_data.pop_front();
}
@@ -44,7 +41,9 @@ bool Bucket::empty()
void Bucket::lock()
{
m_locked = true;
- while (m_locked) { SLEEP(300); }
+ while (m_locked) {
+ SLEEP(300);
+ }
}
void Bucket::unlock()
@@ -58,4 +57,3 @@ bool Bucket::virtualBlockerMethod()
// The return value was added just for diversity sake.
return true;
}
-
diff --git a/sources/shiboken6/tests/libsample/bucket.h b/sources/shiboken6/tests/libsample/bucket.h
index 4a45802a4..73e8edd78 100644
--- a/sources/shiboken6/tests/libsample/bucket.h
+++ b/sources/shiboken6/tests/libsample/bucket.h
@@ -6,6 +6,7 @@
#include "libsamplemacros.h"
#include "objecttype.h"
+
#include <list>
class ObjectType;
@@ -13,7 +14,7 @@ class ObjectType;
class LIBSAMPLE_API Bucket : public ObjectType
{
public:
- Bucket();
+ Bucket() = default;
void push(int);
int pop();
bool empty();
@@ -27,8 +28,7 @@ public:
private:
std::list<int> m_data;
- volatile bool m_locked;
+ volatile bool m_locked = false;
};
#endif // BUCKET_H
-
diff --git a/sources/shiboken6/tests/libsample/bytearray.cpp b/sources/shiboken6/tests/libsample/bytearray.cpp
index 40f1ebc84..78d5162b0 100644
--- a/sources/shiboken6/tests/libsample/bytearray.cpp
+++ b/sources/shiboken6/tests/libsample/bytearray.cpp
@@ -1,13 +1,14 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <cstring>
#include "bytearray.h"
-ByteArray::ByteArray()
+#include <algorithm>
+#include <iterator>
+#include <cstring>
+
+ByteArray::ByteArray() : m_data(1, '\0')
{
- m_data = std::vector<char>(1);
- m_data[0] = '\0';
}
ByteArray::ByteArray(char c)
@@ -17,48 +18,37 @@ ByteArray::ByteArray(char c)
m_data[1] = '\0';
}
-ByteArray::ByteArray(const char* data)
+ByteArray::ByteArray(const char *data)
{
- size_t len = strlen(data);
+ size_t len = std::strlen(data);
m_data = std::vector<char>(len + 1);
memcpy(&m_data[0], data, len);
m_data[len] = '\0';
}
-ByteArray::ByteArray(const char* data, int len)
+ByteArray::ByteArray(const char *data, int len)
{
m_data = std::vector<char>(len + 1);
memcpy(&m_data[0], data, len);
m_data[len] = '\0';
}
-ByteArray::ByteArray(const ByteArray& other)
-{
- m_data = std::vector<char>(other.size() + 1);
- memcpy(&m_data[0], &other.m_data[0], other.size());
- m_data[other.size()] = '\0';
-}
-
-int
-ByteArray::size() const
+int ByteArray::size() const
{
return m_data.size() - 1;
}
-char
-ByteArray::at(int pos) const
+char ByteArray::at(int pos) const
{
return m_data[pos];
}
-const char*
-ByteArray::data() const
+const char *ByteArray::data() const
{
return &(m_data[0]);
}
-ByteArray&
-ByteArray::append(char c)
+ByteArray &ByteArray::append(char c)
{
m_data.pop_back();
m_data.push_back(c);
@@ -66,37 +56,30 @@ ByteArray::append(char c)
return *this;
}
-ByteArray&
-ByteArray::append(const char* data)
+ByteArray &ByteArray::append(const char *data)
{
m_data.pop_back();
- for (int i = 0; i < (int)strlen(data); ++i)
- m_data.push_back(data[i]);
+ std::copy(data, data + strlen(data), std::back_inserter(m_data));
m_data.push_back('\0');
return *this;
}
-ByteArray&
-ByteArray::append(const char* data, int len)
+ByteArray &ByteArray::append(const char *data, int len)
{
m_data.pop_back();
- for (int i = 0; i < len; ++i)
- m_data.push_back(data[i]);
+ std::copy(data, data + len, std::back_inserter(m_data));
m_data.push_back('\0');
return *this;
}
-ByteArray&
-ByteArray::append(const ByteArray& other)
+ByteArray &ByteArray::append(const ByteArray &other)
{
m_data.pop_back();
- for (int i = 0; i < (int)other.m_data.size(); ++i)
- m_data.push_back(other.m_data[i]);
- m_data.push_back('\0');
+ std::copy(other.m_data.begin(), other.m_data.end(), std::back_inserter(m_data));
return *this;
}
-static bool compare(const std::vector<char>& mine, const char* other)
+static bool compare(const std::vector<char> &mine, const char *other)
{
for (int i = 0; i < (int)mine.size() - 1; ++i) {
if (mine[i] != other[i])
@@ -105,85 +88,79 @@ static bool compare(const std::vector<char>& mine, const char* other)
return true;
}
-bool
-ByteArray::operator==(const ByteArray& other) const
+bool ByteArray::operator==(const ByteArray &other) const
{
- return compare(m_data, &other.m_data[0]);
+ return m_data == other.m_data;
}
-bool
-operator==(const ByteArray& ba1, const char* ba2)
+bool operator==(const ByteArray &ba1, const char *ba2)
{
return compare(ba1.m_data, ba2);
}
-bool
-operator==(const char* ba1, const ByteArray& ba2)
+
+bool operator==(const char *ba1, const ByteArray &ba2)
{
return compare(ba2.m_data, ba1);
}
-bool
-ByteArray::operator!=(const ByteArray& other) const
+bool ByteArray::operator!=(const ByteArray &other) const
{
- return !(m_data == other.m_data);
+ return m_data != other.m_data;
}
-bool
-operator!=(const ByteArray& ba1, const char* ba2)
+
+bool operator!=(const ByteArray &ba1, const char *ba2)
{
return !(ba1 == ba2);
}
-bool
-operator!=(const char* ba1, const ByteArray& ba2)
+
+bool operator!=(const char *ba1, const ByteArray &ba2)
{
return !(ba1 == ba2);
}
-ByteArray&
-ByteArray::operator+=(char c)
+ByteArray &ByteArray::operator+=(char c)
{
return append(c);
}
-ByteArray&
-ByteArray::operator+=(const char* data)
+
+ByteArray &ByteArray::operator+=(const char *data)
{
return append(data);
}
-ByteArray&
-ByteArray::operator+=(const ByteArray& other)
+
+ByteArray &ByteArray::operator+=(const ByteArray &other)
{
return append(other);
}
-ByteArray
-operator+(const ByteArray& ba1, const ByteArray& ba2)
+ByteArray operator+(const ByteArray &ba1, const ByteArray &ba2)
{
return ByteArray(ba1) += ba2;
}
-ByteArray
-operator+(const ByteArray& ba1, const char* ba2)
+
+ByteArray operator+(const ByteArray &ba1, const char *ba2)
{
return ByteArray(ba1) += ByteArray(ba2);
}
-ByteArray
-operator+(const char* ba1, const ByteArray& ba2)
+
+ByteArray operator+(const char *ba1, const ByteArray &ba2)
{
return ByteArray(ba1) += ba2;
}
-ByteArray
-operator+(const ByteArray& ba1, char ba2)
+
+ByteArray operator+(const ByteArray &ba1, char ba2)
{
return ByteArray(ba1) += ByteArray(ba2);
}
-ByteArray
-operator+(char ba1, const ByteArray& ba2)
+
+ByteArray operator+(char ba1, const ByteArray &ba2)
{
return ByteArray(ba1) += ba2;
}
-unsigned int
-ByteArray::hash(const ByteArray& byteArray)
+unsigned int ByteArray::hash(const ByteArray &byteArray)
{
unsigned int result = 0;
- for (int i = 0; i < (int)byteArray.m_data.size(); ++i)
- result = 5 * result + byteArray.m_data[i];
+ for (char c : byteArray.m_data)
+ result = 5U * result + unsigned(c);
return result;
}
diff --git a/sources/shiboken6/tests/libsample/bytearray.h b/sources/shiboken6/tests/libsample/bytearray.h
index 3e5d4b100..35ff22367 100644
--- a/sources/shiboken6/tests/libsample/bytearray.h
+++ b/sources/shiboken6/tests/libsample/bytearray.h
@@ -6,59 +6,59 @@
#include "str.h"
#include "libsamplemacros.h"
+
#include <vector>
class LIBSAMPLE_API ByteArray
{
public:
ByteArray();
- ByteArray(char data);
- ByteArray(const char* data);
- ByteArray(const char* data, int len);
- ByteArray(const ByteArray& other);
+ explicit ByteArray(char data);
+ explicit ByteArray(const char *data);
+ explicit ByteArray(const char *data, int len);
int size() const;
char at(int i) const;
char operator[](int i) const;
- const char* data() const;
+ const char *data() const;
- ByteArray& append(char c);
- ByteArray& append(const char* data);
- ByteArray& append(const char* data, int len);
- ByteArray& append(const ByteArray& other);
+ ByteArray &append(char c);
+ ByteArray &append(const char *data);
+ ByteArray &append(const char *data, int len);
+ ByteArray &append(const ByteArray &other);
- bool operator==(const ByteArray& other) const;
- bool operator!=(const ByteArray& other) const;
+ bool operator==(const ByteArray &other) const;
+ bool operator!=(const ByteArray &other) const;
- ByteArray& operator+=(char c);
- ByteArray& operator+=(const char* data);
- ByteArray& operator+=(const ByteArray& other);
+ ByteArray &operator+=(char c);
+ ByteArray &operator+=(const char *data);
+ ByteArray &operator+=(const ByteArray &other);
- static unsigned int hash(const ByteArray& byteArray);
+ static unsigned int hash(const ByteArray &byteArray);
private:
std::vector<char> m_data;
- friend LIBSAMPLE_API bool operator==(const ByteArray& ba1, const char* ba2);
- friend LIBSAMPLE_API bool operator==(const char* ba1, const ByteArray& ba2);
- friend LIBSAMPLE_API bool operator!=(const ByteArray& ba1, const char* ba2);
- friend LIBSAMPLE_API bool operator!=(const char* ba1, const ByteArray& ba2);
+ friend LIBSAMPLE_API bool operator==(const ByteArray &ba1, const char *ba2);
+ friend LIBSAMPLE_API bool operator==(const char *ba1, const ByteArray &ba2);
+ friend LIBSAMPLE_API bool operator!=(const ByteArray &ba1, const char *ba2);
+ friend LIBSAMPLE_API bool operator!=(const char *ba1, const ByteArray &ba2);
- friend LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, const ByteArray& ba2);
- friend LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, const char* ba2);
- friend LIBSAMPLE_API ByteArray operator+(const char* ba1, const ByteArray& ba2);
- friend LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, char ba2);
- friend LIBSAMPLE_API ByteArray operator+(char ba1, const ByteArray& ba2);
+ friend LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, const ByteArray &ba2);
+ friend LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, const char *ba2);
+ friend LIBSAMPLE_API ByteArray operator+(const char *ba1, const ByteArray &ba2);
+ friend LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, char ba2);
+ friend LIBSAMPLE_API ByteArray operator+(char ba1, const ByteArray &ba2);
};
-LIBSAMPLE_API bool operator==(const ByteArray& ba1, const char* ba2);
-LIBSAMPLE_API bool operator==(const char* ba1, const ByteArray& ba2);
-LIBSAMPLE_API bool operator!=(const ByteArray& ba1, const char* ba2);
-LIBSAMPLE_API bool operator!=(const char* ba1, const ByteArray& ba2);
+LIBSAMPLE_API bool operator==(const ByteArray &ba1, const char *ba2);
+LIBSAMPLE_API bool operator==(const char *ba1, const ByteArray &ba2);
+LIBSAMPLE_API bool operator!=(const ByteArray &ba1, const char *ba2);
+LIBSAMPLE_API bool operator!=(const char *ba1, const ByteArray &ba2);
-LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, const ByteArray& ba2);
-LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, const char* ba2);
-LIBSAMPLE_API ByteArray operator+(const char* ba1, const ByteArray& ba2);
-LIBSAMPLE_API ByteArray operator+(const ByteArray& ba1, char ba2);
-LIBSAMPLE_API ByteArray operator+(char ba1, const ByteArray& ba2);
+LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, const ByteArray &ba2);
+LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, const char *ba2);
+LIBSAMPLE_API ByteArray operator+(const char *ba1, const ByteArray &ba2);
+LIBSAMPLE_API ByteArray operator+(const ByteArray &ba1, char ba2);
+LIBSAMPLE_API ByteArray operator+(char ba1, const ByteArray &ba2);
#endif // BYTEARRAY_H
diff --git a/sources/shiboken6/tests/libsample/collector.cpp b/sources/shiboken6/tests/libsample/collector.cpp
index 2adff6628..579239bcb 100644
--- a/sources/shiboken6/tests/libsample/collector.cpp
+++ b/sources/shiboken6/tests/libsample/collector.cpp
@@ -8,13 +8,13 @@ void Collector::clear()
m_items.clear();
}
-Collector& Collector::operator<<(ObjectType::Identifier item)
+Collector &Collector::operator<<(ObjectType::Identifier item)
{
m_items.push_back(item);
return *this;
}
-Collector& Collector::operator<<(const ObjectType *obj)
+Collector &Collector::operator<<(const ObjectType *obj)
{
m_items.push_back(obj->identifier());
return *this;
@@ -25,9 +25,9 @@ std::list<ObjectType::Identifier> Collector::items()
return m_items;
}
-int Collector::size()
+int Collector::size() const
{
- return (int) m_items.size();
+ return int(m_items.size());
}
Collector &operator<<(Collector &s, const IntWrapper &w)
diff --git a/sources/shiboken6/tests/libsample/collector.h b/sources/shiboken6/tests/libsample/collector.h
index 1ef3281e5..26766847a 100644
--- a/sources/shiboken6/tests/libsample/collector.h
+++ b/sources/shiboken6/tests/libsample/collector.h
@@ -4,36 +4,34 @@
#ifndef COLLECTOR_H
#define COLLECTOR_H
-#include <list>
#include "libsamplemacros.h"
-
#include "intwrapper.h"
#include "objecttype.h"
+#include <list>
+
class LIBSAMPLE_API Collector
{
public:
- Collector() {}
- virtual ~Collector() {}
+ Collector() noexcept = default;
+ virtual ~Collector() = default;
+ LIBMINIMAL_DISABLE_COPY_MOVE(Collector)
void clear();
- Collector& operator<<(ObjectType::Identifier item);
+ Collector &operator<<(ObjectType::Identifier item);
- Collector& operator<<(const ObjectType *);
+ Collector &operator<<(const ObjectType *);
std::list<ObjectType::Identifier> items();
- int size();
+ int size() const;
private:
std::list<ObjectType::Identifier> m_items;
-
- Collector(const Collector&);
- Collector& operator=(const Collector&);
};
/* Helper for testing external operators */
-LIBSAMPLE_API Collector &operator<<(Collector&, const IntWrapper&);
+LIBSAMPLE_API Collector &operator<<(Collector &, const IntWrapper &);
#endif // COLLECTOR_H
diff --git a/sources/shiboken6/tests/libsample/complex.cpp b/sources/shiboken6/tests/libsample/complex.cpp
index ce2c2b7de..e3bec9aae 100644
--- a/sources/shiboken6/tests/libsample/complex.cpp
+++ b/sources/shiboken6/tests/libsample/complex.cpp
@@ -1,18 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "complex.h"
-using namespace std;
+#include <iostream>
-Complex::Complex(double real, double imag)
+Complex::Complex(double real, double imag) noexcept
: m_real(real), m_imag(imag)
{
}
-Complex
-Complex::operator+(Complex& other)
+Complex Complex::operator+(const Complex &other)
{
Complex result;
result.setReal(m_real + other.real());
@@ -20,10 +18,7 @@ Complex::operator+(Complex& other)
return result;
}
-void
-Complex::show()
+void Complex::show() const
{
- cout << "(real: " << m_real << ", imag: " << m_imag << ")";
+ std::cout << "(real: " << m_real << ", imag: " << m_imag << ")";
}
-
-
diff --git a/sources/shiboken6/tests/libsample/complex.h b/sources/shiboken6/tests/libsample/complex.h
index 54fb99ed1..168fe5c44 100644
--- a/sources/shiboken6/tests/libsample/complex.h
+++ b/sources/shiboken6/tests/libsample/complex.h
@@ -9,17 +9,19 @@
class LIBSAMPLE_API Complex
{
public:
- Complex(double real = 0.0, double imag = 0.0);
- ~Complex() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Complex)
+
+ explicit Complex(double real = 0.0, double imag = 0.0) noexcept;
+ ~Complex() = default;
inline double real() const { return m_real; }
inline void setReal(double real) { m_real = real; }
inline double imag() const { return m_imag; }
inline void setImaginary(double imag) { m_imag = imag; }
- Complex operator+(Complex& other);
+ Complex operator+(const Complex &other);
- void show();
+ void show() const;
private:
double m_real;
diff --git a/sources/shiboken6/tests/libsample/ctorconvrule.h b/sources/shiboken6/tests/libsample/ctorconvrule.h
index cd7d1c669..a5411b749 100644
--- a/sources/shiboken6/tests/libsample/ctorconvrule.h
+++ b/sources/shiboken6/tests/libsample/ctorconvrule.h
@@ -9,8 +9,10 @@
class CtorConvRule
{
public:
- explicit CtorConvRule(long value) : m_value(value) {}
- virtual ~CtorConvRule() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(CtorConvRule)
+
+ explicit CtorConvRule(long value) noexcept : m_value(value) {}
+ virtual ~CtorConvRule() = default;
virtual void dummyVirtualMethod() {}
long value() { return m_value; }
private:
diff --git a/sources/shiboken6/tests/libsample/cvlist.h b/sources/shiboken6/tests/libsample/cvlist.h
index eb635c83b..e09c7d943 100644
--- a/sources/shiboken6/tests/libsample/cvlist.h
+++ b/sources/shiboken6/tests/libsample/cvlist.h
@@ -12,7 +12,7 @@ class CVValueType
CVValueType();
};
-typedef std::list<const CVValueType*> const_ptr_value_list;
+using const_ptr_value_list = std::list<const CVValueType*>;
// This tests binding generation for a container of a const value type. The
// class doesn't need to do anything; this is just to verify that the generated
@@ -21,8 +21,8 @@ typedef std::list<const CVValueType*> const_ptr_value_list;
class CVListUser
{
public:
- static const_ptr_value_list produce() { return const_ptr_value_list(); }
- static void consume(const const_ptr_value_list& l) { (void)l; }
+ static const_ptr_value_list produce() { return {}; }
+ static void consume(const const_ptr_value_list &l) { (void)l; }
};
#endif // LIST_H
diff --git a/sources/shiboken6/tests/libsample/derived.cpp b/sources/shiboken6/tests/libsample/derived.cpp
index ad68d2614..d20880431 100644
--- a/sources/shiboken6/tests/libsample/derived.cpp
+++ b/sources/shiboken6/tests/libsample/derived.cpp
@@ -1,44 +1,36 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "derived.h"
-using namespace std;
+#include <iostream>
-Derived::Derived(int id) : Abstract(id)
+Derived::Derived(int id) noexcept : Abstract(id)
{
}
-Derived::~Derived()
-{
-}
+Derived::~Derived() = default;
-Abstract*
-Derived::createObject()
+Abstract *Derived::createObject()
{
static int id = 100;
return new Derived(id++);
}
-void
-Derived::pureVirtual()
+void Derived::pureVirtual()
{
}
-void*
-Derived::pureVirtualReturningVoidPtr()
+void *Derived::pureVirtualReturningVoidPtr()
{
return nullptr;
}
-void
-Derived::unpureVirtual()
+void Derived::unpureVirtual()
{
}
-bool
-Derived::singleArgument(bool b)
+bool Derived::singleArgument(bool b)
{
return !b;
}
@@ -49,40 +41,36 @@ Derived::defaultValue(int n)
return ((double) n) + 0.1;
}
-OverloadedFuncEnum
-Derived::overloaded(int i, int d)
+OverloadedFuncEnum Derived::overloaded(int, int)
{
return OverloadedFunc_ii;
}
-OverloadedFuncEnum
-Derived::overloaded(double n)
+OverloadedFuncEnum Derived::overloaded(double)
{
return OverloadedFunc_d;
}
-Derived::OtherOverloadedFuncEnum
-Derived::otherOverloaded(int a, int b, bool c, double d)
+Derived::OtherOverloadedFuncEnum Derived::otherOverloaded(int, int, bool, double)
{
return OtherOverloadedFunc_iibd;
}
-Derived::OtherOverloadedFuncEnum
-Derived::otherOverloaded(int a, double b)
+Derived::OtherOverloadedFuncEnum Derived::otherOverloaded(int, double)
{
return OtherOverloadedFunc_id;
}
struct SecretClass : public Abstract {
- virtual void pureVirtual() {}
- virtual void *pureVirtualReturningVoidPtr() { return nullptr; }
- virtual PrintFormat returnAnEnum() { return Short; }
- void hideFunction(HideType*){};
+ void pureVirtual() override {}
+ void *pureVirtualReturningVoidPtr() override { return nullptr; }
+ PrintFormat returnAnEnum() override { return Short; }
+ void hideFunction(HideType*) override {};
private:
- virtual void pureVirtualPrivate() {}
+ void pureVirtualPrivate() override {}
};
-Abstract* Derived::triggerImpossibleTypeDiscovery()
+Abstract *Derived::triggerImpossibleTypeDiscovery()
{
return new SecretClass;
}
@@ -90,7 +78,7 @@ Abstract* Derived::triggerImpossibleTypeDiscovery()
struct AnotherSecretClass : public Derived {
};
-Abstract* Derived::triggerAnotherImpossibleTypeDiscovery()
+Abstract *Derived::triggerAnotherImpossibleTypeDiscovery()
{
return new AnotherSecretClass;
}
diff --git a/sources/shiboken6/tests/libsample/derived.h b/sources/shiboken6/tests/libsample/derived.h
index 5d5010857..b7736c37a 100644
--- a/sources/shiboken6/tests/libsample/derived.h
+++ b/sources/shiboken6/tests/libsample/derived.h
@@ -15,6 +15,8 @@ enum OverloadedFuncEnum {
class LIBSAMPLE_API Derived : public Abstract
{
public:
+ LIBMINIMAL_DISABLE_COPY_MOVE(Derived)
+
enum OtherOverloadedFuncEnum {
OtherOverloadedFunc_iibd,
OtherOverloadedFunc_id
@@ -23,21 +25,21 @@ public:
class SomeInnerClass {
public:
void uselessMethod() {}
- SomeInnerClass operator+(const SomeInnerClass& other) { return other; }
- bool operator==(const SomeInnerClass& other) { return true; }
+ SomeInnerClass operator+(const SomeInnerClass &other) { return other; }
+ bool operator==(const SomeInnerClass &) { return true; }
};
- Derived(int id = -1);
+ explicit Derived(int id = -1) noexcept;
~Derived() override;
void pureVirtual() override;
- void* pureVirtualReturningVoidPtr() override;
+ void *pureVirtualReturningVoidPtr() override;
void unpureVirtual() override;
PrintFormat returnAnEnum() override { return Short; }
Type type() const override { return TpDerived; }
// factory method
- static Abstract* createObject();
+ static Abstract *createObject();
// single argument
bool singleArgument(bool b);
@@ -53,15 +55,15 @@ public:
OtherOverloadedFuncEnum otherOverloaded(int a, int b, bool c, double d);
OtherOverloadedFuncEnum otherOverloaded(int a, double b);
- inline SomeInnerClass returnMyParameter(const SomeInnerClass& s) { return s; }
+ inline SomeInnerClass returnMyParameter(const SomeInnerClass &s) { return s; }
- static Abstract* triggerImpossibleTypeDiscovery();
- static Abstract* triggerAnotherImpossibleTypeDiscovery();
+ static Abstract *triggerImpossibleTypeDiscovery();
+ static Abstract *triggerAnotherImpossibleTypeDiscovery();
void hideFunction(HideType*) override {}
protected:
- const char* getClassName() { return className(); }
- virtual const char* className() override { return "Derived"; }
+ const char *getClassName() { return className(); }
+ virtual const char *className() const override { return "Derived"; }
private:
void pureVirtualPrivate() override;
diff --git a/sources/shiboken6/tests/libsample/echo.h b/sources/shiboken6/tests/libsample/echo.h
index 4a655fec1..01b11a4a6 100644
--- a/sources/shiboken6/tests/libsample/echo.h
+++ b/sources/shiboken6/tests/libsample/echo.h
@@ -12,19 +12,49 @@ class ObjectType;
class Echo
{
public:
- Echo(){}
- ~Echo(){}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Echo)
- void doNothingWithConstBool(const bool hi) {}
- void methodWithNamedArg(const Str& string = Str("")) {}
+ Echo() noexcept = default;
+ ~Echo() = default;
- Str operator()(const Str& s, const int i) { return s + i; }
+ void doNothingWithConstBool(const bool hi);
+ void methodWithNamedArg(const Str &string = Str{});
+
+ Str operator()(const Str &s, const int i) { return s + i; }
// These method are here just for compilation test purposes
- Echo& operator<<(unsigned int item) { return *this; }
- Echo& operator<<(signed int item) { return *this; }
- Echo& operator<<(const ObjectType* item) { return *this; }
- Echo& operator<<(Str str) { return *this; }
+ Echo &operator<<(unsigned int item);
+ Echo &operator<<(signed int item);
+ Echo &operator<<(const ObjectType *item);
+ Echo &operator<<(Str str);
};
-#endif
+inline void Echo::doNothingWithConstBool(const bool)
+{
+}
+
+inline void Echo::methodWithNamedArg(const Str &)
+{
+}
+
+inline Echo &Echo::operator<<(unsigned int)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(signed int)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(const ObjectType *)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(Str)
+{
+ return *this;
+}
+
+#endif // ECHO_H
diff --git a/sources/shiboken6/tests/libsample/exceptiontest.cpp b/sources/shiboken6/tests/libsample/exceptiontest.cpp
index 35da4e90b..56144e086 100644
--- a/sources/shiboken6/tests/libsample/exceptiontest.cpp
+++ b/sources/shiboken6/tests/libsample/exceptiontest.cpp
@@ -37,3 +37,10 @@ void ExceptionTest::voidThrowInt(bool doThrow)
if (doThrow)
throw 42;
}
+
+ExceptionTest *ExceptionTest::create(bool doThrow)
+{
+ if (doThrow)
+ throw TestException();
+ return new ExceptionTest;
+}
diff --git a/sources/shiboken6/tests/libsample/exceptiontest.h b/sources/shiboken6/tests/libsample/exceptiontest.h
index 4931fc2ed..b5812a090 100644
--- a/sources/shiboken6/tests/libsample/exceptiontest.h
+++ b/sources/shiboken6/tests/libsample/exceptiontest.h
@@ -18,6 +18,8 @@ class LIBSAMPLE_API ExceptionTest
int intThrowInt(bool doThrow);
void voidThrowInt(bool doThrow);
+
+ static ExceptionTest *create(bool doThrow);
};
#endif // EXCEPTIONTEST_H
diff --git a/sources/shiboken6/tests/libsample/expression.cpp b/sources/shiboken6/tests/libsample/expression.cpp
index 21a51a288..6f3c5fdc5 100644
--- a/sources/shiboken6/tests/libsample/expression.cpp
+++ b/sources/shiboken6/tests/libsample/expression.cpp
@@ -3,112 +3,77 @@
#include "expression.h"
-#include <sstream>
-
-Expression::Expression() : m_value(0), m_operation(None), m_operand1(nullptr), m_operand2(nullptr)
-{
-}
-
-Expression::Expression(int number) : m_value(number), m_operation(None), m_operand1(nullptr), m_operand2(nullptr)
-{
-}
-Expression::Expression(const Expression& other)
-{
- m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : nullptr;
- m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : nullptr;
- m_value = other.m_value;
- m_operation = other.m_operation;
-}
+#include <sstream>
-Expression& Expression::operator=(const Expression& other)
-{
- if (&other == this)
- return *this;
- delete m_operand1;
- delete m_operand2;
- m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : nullptr;
- m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : nullptr;
- m_operation = other.m_operation;
- m_value = other.m_value;
- return *this;
-}
+Expression::Expression() noexcept = default;
-Expression::~Expression()
+Expression::Expression(int number) noexcept : m_value(number)
{
- delete m_operand1;
- delete m_operand2;
}
-Expression Expression::operator+(const Expression& other)
+Expression Expression::operator+(const Expression &other)
{
Expression expr;
expr.m_operation = Add;
- expr.m_operand1 = new Expression(*this);
- expr.m_operand2 = new Expression(other);
+ expr.m_operand1 = std::make_shared<Expression>(*this);
+ expr.m_operand2 = std::make_shared<Expression>(other);
return expr;
}
-Expression Expression::operator-(const Expression& other)
+Expression Expression::operator-(const Expression &other)
{
Expression expr;
expr.m_operation = Add;
- expr.m_operand1 = new Expression(*this);
- expr.m_operand2 = new Expression(other);
+ expr.m_operand1 = std::make_shared<Expression>(*this);
+ expr.m_operand2 = std::make_shared<Expression>(other);
return expr;
}
-Expression Expression::operator<(const Expression& other)
+Expression Expression::operator<(const Expression &other)
{
Expression expr;
expr.m_operation = LessThan;
- expr.m_operand1 = new Expression(*this);
- expr.m_operand2 = new Expression(other);
+ expr.m_operand1 = std::make_shared<Expression>(*this);
+ expr.m_operand2 = std::make_shared<Expression>(other);
return expr;
}
-Expression Expression::operator>(const Expression& other)
+Expression Expression::operator>(const Expression &other)
{
Expression expr;
expr.m_operation = GreaterThan;
- expr.m_operand1 = new Expression(*this);
- expr.m_operand2 = new Expression(other);
+ expr.m_operand1 = std::make_shared<Expression>(*this);
+ expr.m_operand2 = std::make_shared<Expression>(other);
return expr;
}
std::string Expression::toString() const
{
+ std::ostringstream s;
if (m_operation == None) {
- std::ostringstream s;
s << m_value;
return s.str();
}
- std::string result;
- result += '(';
- result += m_operand1->toString();
- char op;
+ s << '(' << m_operand1->toString();
switch (m_operation) {
case Add:
- op = '+';
+ s << '+';
break;
case Sub:
- op = '-';
+ s << '-';
break;
case LessThan:
- op = '<';
+ s << '<';
break;
case GreaterThan:
- op = '<';
+ s << '<';
break;
- case None: // just to avoid the compiler warning
default:
- op = '?';
+ s << '?';
break;
}
- result += op;
- result += m_operand2->toString();
- result += ')';
- return result;
+ s << m_operand2->toString() << ')';
+ return s.str();
}
-
diff --git a/sources/shiboken6/tests/libsample/expression.h b/sources/shiboken6/tests/libsample/expression.h
index cf41cb620..e7c5b7306 100644
--- a/sources/shiboken6/tests/libsample/expression.h
+++ b/sources/shiboken6/tests/libsample/expression.h
@@ -6,34 +6,35 @@
#define EXPRESSION_H
#include "libsamplemacros.h"
+
+#include <memory>
#include <string>
class LIBSAMPLE_API Expression
{
public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Expression)
+
enum Operation {
None, Add, Sub, LessThan, GreaterThan
};
- Expression(int number);
- Expression(const Expression& other);
- Expression& operator=(const Expression& other);
-
- ~Expression();
+ explicit Expression(int number) noexcept;
+ ~Expression() = default;
- Expression operator>(const Expression& other);
- Expression operator<(const Expression& other);
- Expression operator+(const Expression& other);
- Expression operator-(const Expression& other);
+ Expression operator>(const Expression &other);
+ Expression operator<(const Expression &other);
+ Expression operator+(const Expression &other);
+ Expression operator-(const Expression &other);
std::string toString() const;
private:
- int m_value;
- Operation m_operation;
- Expression* m_operand1;
- Expression* m_operand2;
+ int m_value = 0;
+ Operation m_operation = None;
+ std::shared_ptr<Expression> m_operand1;
+ std::shared_ptr<Expression> m_operand2;
- Expression();
+ Expression() noexcept;
};
#endif // EXPRESSION_H
diff --git a/sources/shiboken6/tests/libsample/filter.cpp b/sources/shiboken6/tests/libsample/filter.cpp
index 3f2ac70b0..950847985 100644
--- a/sources/shiboken6/tests/libsample/filter.cpp
+++ b/sources/shiboken6/tests/libsample/filter.cpp
@@ -1,44 +1,34 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <string>
#include "filter.h"
+
Data::Data(Field field, std::string value)
: m_field(field), m_value(value)
{
}
-Union::Union(const Data& filter)
+Union::Union(const Data &filter)
{
m_filters.push_back(filter);
}
-Union::Union(const Intersection& filter)
+Union::Union(const Intersection &filter)
{
m_filters.push_back(filter);
}
-Union::Union(const Union& filter)
-{
- m_filters = filter.filters();
-}
-
-Intersection::Intersection(const Data& filter)
+Intersection::Intersection(const Data &filter)
{
m_filters.push_back(filter);
}
-Intersection::Intersection(const Union& filter)
+Intersection::Intersection(const Union &filter)
{
m_filters.push_back(filter);
}
-Intersection::Intersection(const Intersection& filter)
-{
- m_filters = filter.filters();
-}
-
-Intersection operator&(const Intersection& a, const Intersection& b)
+Intersection operator&(const Intersection &a, const Intersection &b)
{
Intersection filter;
filter.addFilter(a);
diff --git a/sources/shiboken6/tests/libsample/filter.h b/sources/shiboken6/tests/libsample/filter.h
index 266785ad7..d82d38eb8 100644
--- a/sources/shiboken6/tests/libsample/filter.h
+++ b/sources/shiboken6/tests/libsample/filter.h
@@ -4,11 +4,11 @@
#ifndef FILTER_H
#define FILTER_H
+#include "libsamplemacros.h"
+
#include <string>
#include <list>
-#include "libsamplemacros.h"
-
class Intersection;
class LIBSAMPLE_API Filter
@@ -17,7 +17,6 @@ class LIBSAMPLE_API Filter
class LIBSAMPLE_API Data : public Filter
{
-
public:
enum Field {
Name,
@@ -25,7 +24,7 @@ public:
Year
};
- Data(Field field, std::string value);
+ explicit Data(Field field, std::string value);
Field field() const { return m_field; }
std::string value() const { return m_value; }
@@ -39,13 +38,12 @@ class LIBSAMPLE_API Union : public Filter
{
public:
- Union(const Data&);
- Union(const Intersection&);
- Union() {};
- Union(const Union&);
+ Union(const Data &);
+ Union(const Intersection &);
+ Union() = default;
std::list<Filter> filters() const { return m_filters; }
- void addFilter(const Filter& data) { m_filters.push_back(data); }
+ void addFilter(const Filter &data) { m_filters.push_back(data); }
private:
std::list<Filter> m_filters;
@@ -54,20 +52,18 @@ private:
class LIBSAMPLE_API Intersection : public Filter
{
public:
-
- Intersection(const Data&);
- Intersection(const Union&);
- Intersection() {};
- Intersection(const Intersection&);
+ Intersection(const Data &);
+ Intersection(const Union &);
+ Intersection() = default;
std::list<Filter> filters() const { return m_filters; }
- void addFilter(const Filter& data) { m_filters.push_back(data); }
+ void addFilter(const Filter &data) { m_filters.push_back(data); }
private:
std::list<Filter> m_filters;
};
-LIBSAMPLE_API Intersection operator&(const Intersection& a, const Intersection& b);
+LIBSAMPLE_API Intersection operator&(const Intersection &a, const Intersection &b);
#endif // FILTER_H
diff --git a/sources/shiboken6/tests/libsample/functions.cpp b/sources/shiboken6/tests/libsample/functions.cpp
index 7325aad3a..ad2f4dd5a 100644
--- a/sources/shiboken6/tests/libsample/functions.cpp
+++ b/sources/shiboken6/tests/libsample/functions.cpp
@@ -2,37 +2,33 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "functions.h"
-#include <string.h>
+#include "polygon.h"
+
+#include <cstring>
#include <algorithm>
#include <iostream>
#include <numeric>
-using namespace std;
-
-void
-printSomething()
+void printSomething()
{
- cout << __FUNCTION__ << endl;
+ std::cout << __FUNCTION__ << std::endl;
}
-int
-gimmeInt()
+int gimmeInt()
{
static int val = 2;
val = val * 1.3;
return val;
}
-double
-gimmeDouble()
+double gimmeDouble()
{
static double val = 7.77;
val = val * 1.3;
return val;
}
-std::list<Complex>
-gimmeComplexList()
+std::list<Complex> gimmeComplexList()
{
std::list<Complex> lst;
lst.push_back(Complex());
@@ -41,135 +37,114 @@ gimmeComplexList()
return lst;
}
-Complex
-sumComplexPair(std::pair<Complex, Complex> cpx_pair)
+Complex sumComplexPair(std::pair<Complex, Complex> cpx_pair)
{
return cpx_pair.first + cpx_pair.second;
}
-double
-multiplyPair(std::pair<double, double> pair)
+double multiplyPair(std::pair<double, double> pair)
{
return pair.first * pair.second;
}
-int
-countCharacters(const char* text)
+int countCharacters(const char *text)
{
- if (!text)
- return -1;
- int count;
- for(count = 0; text[count] != '\0'; count++)
- ;
- return count;
+ return text != nullptr ? int(std::strlen(text)) : -1;
}
-char*
-makeCString()
+char *makeCString()
{
- char* string = new char[strlen(__FUNCTION__) + 1];
- strcpy(string, __FUNCTION__);
+ char *string = new char[std::strlen(__FUNCTION__) + 1];
+ std::strcpy(string, __FUNCTION__);
return string;
}
-const char*
-returnCString()
+const char *returnCString()
{
return __FUNCTION__;
}
-GlobalOverloadFuncEnum
-overloadedFunc(int val)
+GlobalOverloadFuncEnum overloadedFunc(int)
{
return GlobalOverloadFunc_i;
}
-GlobalOverloadFuncEnum
-overloadedFunc(double val)
+GlobalOverloadFuncEnum overloadedFunc(double)
{
return GlobalOverloadFunc_d;
}
-char*
-returnNullPrimitivePointer()
+char *returnNullPrimitivePointer()
{
return nullptr;
}
-ObjectType*
-returnNullObjectTypePointer()
+ObjectType *returnNullObjectTypePointer()
{
return nullptr;
}
-Event*
-returnNullValueTypePointer()
+Event *returnNullValueTypePointer()
{
return nullptr;
}
-unsigned int
-doubleUnsignedInt(unsigned int value)
+unsigned int doubleUnsignedInt(unsigned int value)
{
return value * 2;
}
-long long
-doubleLongLong(long long value)
+long long doubleLongLong(long long value)
{
return value * 2;
}
-unsigned long long
-doubleUnsignedLongLong(unsigned long long value)
+unsigned long long doubleUnsignedLongLong(unsigned long long value)
{
return value * 2;
}
-short
-doubleShort(short value)
+short doubleShort(short value)
{
return value * 2;
}
-int
-acceptInt(int x)
+int acceptInt(int x)
{
return x;
}
-unsigned int
-acceptUInt(unsigned int x)
+const int *acceptIntReturnPtr(int x)
+{
+ return new int(x);
+}
+
+unsigned int acceptUInt(unsigned int x)
{
return x;
}
-long
-acceptLong(long x)
+long acceptLong(long x)
{
return x;
}
-unsigned long
-acceptULong(unsigned long x)
+unsigned long acceptULong(unsigned long x)
{
return x;
}
-double
-acceptDouble(double x)
+double acceptDouble(double x)
{
return x;
}
-int
-acceptIntReference(int& x)
+int acceptIntReference(int &x)
{
return x;
}
-OddBool
-acceptOddBoolReference(OddBool& x)
+OddBool acceptOddBoolReference(OddBool &x)
{
return x;
}
@@ -204,9 +179,7 @@ double sumDoubleMatrix(double m[2][3])
return result;
}
-ArrayModifyTest::ArrayModifyTest()
-{
-}
+ArrayModifyTest::ArrayModifyTest() = default;
int ArrayModifyTest::sumIntArray(int n, int *array)
{
@@ -229,7 +202,7 @@ void ClassWithFunctionPointer::doNothing(void *operand)
(void) operand;
}
-string addStdStrings(const std::string &s1, const std::string &s2)
+std::string addStdStrings(const std::string &s1, const std::string &s2)
{
return s1 + s2;
}
@@ -241,5 +214,19 @@ std::wstring addStdWStrings(const std::wstring &s1, const std::wstring &s2)
void testNullPtrT(std::nullptr_t)
{
- cout << __FUNCTION__ << '\n';
+ std::cout << __FUNCTION__ << '\n';
+}
+
+int takePolygon(Polygon &&p)
+{
+ auto p2 = std::move(p);
+ std::cout << __FUNCTION__ << ' ' << p2.points().size() << " points\n";
+ return int(p2.points().size());
+}
+
+int takeObjectType(ObjectType &&o)
+{
+ auto o2 = std::move(o);
+ std::cout << __FUNCTION__ << ' ' << o2.objectName().cstring() << '\n';
+ return o2.objectName().size();
}
diff --git a/sources/shiboken6/tests/libsample/functions.h b/sources/shiboken6/tests/libsample/functions.h
index 7492ec4c2..b745aed6b 100644
--- a/sources/shiboken6/tests/libsample/functions.h
+++ b/sources/shiboken6/tests/libsample/functions.h
@@ -5,12 +5,15 @@
#define FUNCTIONS_H
#include "libsamplemacros.h"
-#include <list>
-#include <utility>
#include "oddbool.h"
#include "complex.h"
#include "objecttype.h"
+#include <list>
+#include <utility>
+
+class Polygon;
+
enum GlobalEnum {
NoThing,
FirstThing,
@@ -30,13 +33,13 @@ LIBSAMPLE_API double multiplyPair(std::pair<double, double> pair);
LIBSAMPLE_API std::list<Complex> gimmeComplexList();
LIBSAMPLE_API Complex sumComplexPair(std::pair<Complex, Complex> cpx_pair);
-LIBSAMPLE_API int countCharacters(const char* text);
-LIBSAMPLE_API char* makeCString();
-LIBSAMPLE_API const char* returnCString();
+LIBSAMPLE_API int countCharacters(const char *text);
+LIBSAMPLE_API char *makeCString();
+LIBSAMPLE_API const char *returnCString();
-LIBSAMPLE_API char* returnNullPrimitivePointer();
-LIBSAMPLE_API ObjectType* returnNullObjectTypePointer();
-LIBSAMPLE_API Event* returnNullValueTypePointer();
+LIBSAMPLE_API char *returnNullPrimitivePointer();
+LIBSAMPLE_API ObjectType *returnNullObjectTypePointer();
+LIBSAMPLE_API Event *returnNullValueTypePointer();
// Tests overloading on functions (!methods)
LIBSAMPLE_API GlobalOverloadFuncEnum overloadedFunc(int val);
@@ -48,13 +51,14 @@ LIBSAMPLE_API unsigned long long doubleUnsignedLongLong(unsigned long long value
LIBSAMPLE_API short doubleShort(short value);
LIBSAMPLE_API int acceptInt(int x);
+LIBSAMPLE_API const int *acceptIntReturnPtr(int x);
LIBSAMPLE_API unsigned int acceptUInt(unsigned int x);
LIBSAMPLE_API long acceptLong(long x);
LIBSAMPLE_API unsigned long acceptULong(unsigned long x);
LIBSAMPLE_API double acceptDouble(double x);
-LIBSAMPLE_API int acceptIntReference(int& x);
-LIBSAMPLE_API OddBool acceptOddBoolReference(OddBool& x);
+LIBSAMPLE_API int acceptIntReference(int &x);
+LIBSAMPLE_API OddBool acceptOddBoolReference(OddBool &x);
LIBSAMPLE_API int sumIntArray(int array[4]);
LIBSAMPLE_API double sumDoubleArray(double array[4]);
@@ -66,6 +70,9 @@ LIBSAMPLE_API std::wstring addStdWStrings(const std::wstring &s1, const std::wst
LIBSAMPLE_API void testNullPtrT(std::nullptr_t);
+LIBSAMPLE_API int takePolygon(Polygon &&p);
+LIBSAMPLE_API int takeObjectType(ObjectType &&o);
+
class LIBSAMPLE_API ArrayModifyTest
{
public:
diff --git a/sources/shiboken6/tests/libsample/handle.cpp b/sources/shiboken6/tests/libsample/handle.cpp
index e92c24c89..93c2abe47 100644
--- a/sources/shiboken6/tests/libsample/handle.cpp
+++ b/sources/shiboken6/tests/libsample/handle.cpp
@@ -3,17 +3,17 @@
#include "handle.h"
-HANDLE HandleHolder::createHandle()
+SAMPLE_HANDLE HandleHolder::createHandle()
{
- return (HANDLE) new OBJ;
+ return (SAMPLE_HANDLE) new OBJ;
}
-bool HandleHolder::compare(HandleHolder* other)
+bool HandleHolder::compare(HandleHolder *other)
{
return other->m_handle == m_handle;
}
-bool HandleHolder::compare2(HandleHolder* other)
+bool HandleHolder::compare2(HandleHolder *other)
{
return other->m_handle2 == m_handle2;
}
diff --git a/sources/shiboken6/tests/libsample/handle.h b/sources/shiboken6/tests/libsample/handle.h
index d54dd9f11..07fc89d15 100644
--- a/sources/shiboken6/tests/libsample/handle.h
+++ b/sources/shiboken6/tests/libsample/handle.h
@@ -8,35 +8,41 @@
/* See http://bugs.pyside.org/show_bug.cgi?id=1105. */
namespace Foo {
- using HANDLE = unsigned long;
+ using SAMPLE_HANDLE = unsigned long;
}
class LIBSAMPLE_API OBJ
{
};
-using HANDLE = OBJ *;
+using SAMPLE_HANDLE = OBJ *;
class LIBSAMPLE_API HandleHolder
{
public:
- explicit HandleHolder(HANDLE ptr = nullptr) : m_handle(ptr) {}
- explicit HandleHolder(Foo::HANDLE val): m_handle2(val) {}
+ explicit HandleHolder(SAMPLE_HANDLE ptr = nullptr) : m_handle(ptr) {}
+ explicit HandleHolder(Foo::SAMPLE_HANDLE val): m_handle2(val) {}
- inline void set(HANDLE ptr) { HANDLE tmp; tmp = m_handle; m_handle = tmp; }
- inline void set(const Foo::HANDLE& val) { m_handle2 = val; }
- inline HANDLE handle() { return m_handle; }
- inline Foo::HANDLE handle2() { return m_handle2; }
+ void set(SAMPLE_HANDLE ptr);
+ inline void set(const Foo::SAMPLE_HANDLE &val) { m_handle2 = val; }
+ inline SAMPLE_HANDLE handle() const { return m_handle; }
+ inline Foo::SAMPLE_HANDLE handle2() const { return m_handle2; }
- static HANDLE createHandle();
- bool compare(HandleHolder* other);
- bool compare2(HandleHolder* other);
+ static SAMPLE_HANDLE createHandle();
+ bool compare(HandleHolder *other);
+ bool compare2(HandleHolder *other);
private:
- HANDLE m_handle;
- Foo::HANDLE m_handle2;
+ SAMPLE_HANDLE m_handle = nullptr;
+ Foo::SAMPLE_HANDLE m_handle2 = 0;
};
+inline void HandleHolder::set(SAMPLE_HANDLE)
+{
+ SAMPLE_HANDLE tmp = m_handle;
+ m_handle = tmp;
+}
+
struct LIBSAMPLE_API PrimitiveStruct {};
using PrimitiveStructPtr = struct PrimitiveStruct *;
struct LIBSAMPLE_API PrimitiveStructPointerHolder
diff --git a/sources/shiboken6/tests/libsample/implicitconv.cpp b/sources/shiboken6/tests/libsample/implicitconv.cpp
index 054aa4b75..887fa6b1c 100644
--- a/sources/shiboken6/tests/libsample/implicitconv.cpp
+++ b/sources/shiboken6/tests/libsample/implicitconv.cpp
@@ -3,39 +3,37 @@
#include "implicitconv.h"
-ImplicitConv
-ImplicitConv::implicitConvCommon(ImplicitConv implicit)
+ImplicitConv::ImplicitConv(const Null &) :
+ m_ctorEnum(CtorPrimitiveType)
+{
+}
+
+ImplicitConv ImplicitConv::implicitConvCommon(ImplicitConv implicit)
{
return implicit;
}
-ImplicitConv
-ImplicitConv::implicitConvDefault(ImplicitConv implicit)
+ImplicitConv ImplicitConv::implicitConvDefault(ImplicitConv implicit)
{
return implicit;
}
-ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(ImplicitConv implicit, int dummyArg)
+ImplicitConv::ICOverloadedFuncEnum ImplicitConv::implicitConvOverloading(ImplicitConv, int)
{
return ImplicitConv::OverFunc_Ii;
}
-ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(ImplicitConv implicit, bool dummyArg)
+ImplicitConv::ICOverloadedFuncEnum ImplicitConv::implicitConvOverloading(ImplicitConv, bool)
{
return ImplicitConv::OverFunc_Ib;
}
-ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(int dummyArg)
+ImplicitConv::ICOverloadedFuncEnum ImplicitConv::implicitConvOverloading(int)
{
return ImplicitConv::OverFunc_i;
}
-ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(CtorEnum dummyArg)
+ImplicitConv::ICOverloadedFuncEnum ImplicitConv::implicitConvOverloading(CtorEnum)
{
return ImplicitConv::OverFunc_C;
}
-
diff --git a/sources/shiboken6/tests/libsample/implicitconv.h b/sources/shiboken6/tests/libsample/implicitconv.h
index aafd919b9..5d69eb487 100644
--- a/sources/shiboken6/tests/libsample/implicitconv.h
+++ b/sources/shiboken6/tests/libsample/implicitconv.h
@@ -12,6 +12,8 @@ class ObjectType;
class LIBSAMPLE_API ImplicitConv
{
public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(ImplicitConv)
+
enum CtorEnum {
CtorNone,
CtorOne,
@@ -28,17 +30,17 @@ public:
OverFunc_C
};
- ImplicitConv() : m_ctorEnum(CtorNone), m_objId(-1), m_value(-1.0) {}
- ImplicitConv(int objId) : m_ctorEnum(CtorOne), m_objId(objId), m_value(-1.0) {}
- ImplicitConv(CtorEnum ctorEnum) : m_ctorEnum(ctorEnum), m_objId(-1), m_value(-1.0) {}
- ImplicitConv(ObjectType&) : m_ctorEnum(CtorObjectTypeReference), m_objId(-1), m_value(-1.0) {}
+ ImplicitConv() noexcept = default;
+ ImplicitConv(int objId) noexcept : m_ctorEnum(CtorOne), m_objId(objId) {}
+ ImplicitConv(CtorEnum ctorEnum) : m_ctorEnum(ctorEnum) {}
+ ImplicitConv(ObjectType&) : m_ctorEnum(CtorObjectTypeReference) {}
ImplicitConv(double value, bool=true) : m_ctorEnum(CtorNone), m_value(value) {}
- ImplicitConv(const Null& null) : m_ctorEnum(CtorPrimitiveType) {}
- ~ImplicitConv() {}
+ ImplicitConv(const Null &null);
+ ~ImplicitConv() = default;
- inline CtorEnum ctorEnum() { return m_ctorEnum; }
- inline int objId() { return m_objId; }
- inline double value() { return m_value; }
+ inline CtorEnum ctorEnum() const { return m_ctorEnum; }
+ inline int objId() const { return m_objId; }
+ inline double value() const { return m_value; }
static ImplicitConv implicitConvCommon(ImplicitConv implicit);
@@ -50,9 +52,9 @@ public:
static ICOverloadedFuncEnum implicitConvOverloading(CtorEnum dummyArg);
private:
- CtorEnum m_ctorEnum;
- int m_objId;
- double m_value;
+ CtorEnum m_ctorEnum = CtorNone;
+ int m_objId = -1;
+ double m_value = -1.0;
};
#endif // IMPLICITCONV_H
diff --git a/sources/shiboken6/tests/libsample/injectcode.cpp b/sources/shiboken6/tests/libsample/injectcode.cpp
index 488f7faae..707d14ed8 100644
--- a/sources/shiboken6/tests/libsample/injectcode.cpp
+++ b/sources/shiboken6/tests/libsample/injectcode.cpp
@@ -2,20 +2,15 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "injectcode.h"
-#include <sstream>
-using namespace std;
+#include <sstream>
-InjectCode::InjectCode()
-{
-}
+InjectCode::InjectCode() noexcept = default;
-InjectCode::~InjectCode()
-{
-}
+InjectCode::~InjectCode() = default;
template<typename T>
-const char* InjectCode::toStr(const T& value)
+const char *InjectCode::toStr(const T &value)
{
std::ostringstream s;
s << value;
@@ -23,41 +18,41 @@ const char* InjectCode::toStr(const T& value)
return m_valueHolder.c_str();
}
-const char* InjectCode::simpleMethod1(int arg0, int arg1)
+const char *InjectCode::simpleMethod1(int arg0, int arg1)
{
return toStr(arg0 + arg1);
}
-const char* InjectCode::simpleMethod2()
+const char *InjectCode::simpleMethod2()
{
return "_";
}
-const char* InjectCode::simpleMethod3(int argc, char** argv)
+const char *InjectCode::simpleMethod3(int argc, char **argv)
{
for (int i = 0; i < argc; ++i)
m_valueHolder += argv[i];
return m_valueHolder.c_str();
}
-const char* InjectCode::overloadedMethod(int arg0, bool arg1)
+const char *InjectCode::overloadedMethod(int arg0, bool arg1)
{
toStr(arg0);
m_valueHolder += arg1 ? "true" : "false";
return m_valueHolder.c_str();
}
-const char* InjectCode::overloadedMethod(int arg0, double arg1)
+const char *InjectCode::overloadedMethod(int arg0, double arg1)
{
return toStr(arg0 + arg1);
}
-const char* InjectCode::overloadedMethod(int argc, char** argv)
+const char *InjectCode::overloadedMethod(int argc, char **argv)
{
return simpleMethod3(argc, argv);
}
-const char* InjectCode::virtualMethod(int arg)
+const char *InjectCode::virtualMethod(int arg)
{
return toStr(arg);
}
@@ -70,13 +65,13 @@ int InjectCode::arrayMethod(int count, int *values) const
return ret;
}
-int InjectCode::sumArrayAndLength(int* values) const
+int InjectCode::sumArrayAndLength(int *values) const
{
int sum = 0;
- while(*values) {
+ while (*values) {
sum = sum + *values + 1;
- values++;
+ ++values;
}
return sum;
diff --git a/sources/shiboken6/tests/libsample/injectcode.h b/sources/shiboken6/tests/libsample/injectcode.h
index 43a3e8468..74046dad5 100644
--- a/sources/shiboken6/tests/libsample/injectcode.h
+++ b/sources/shiboken6/tests/libsample/injectcode.h
@@ -5,27 +5,31 @@
#define INJECTCODE_H
#include "libsamplemacros.h"
+
#include <utility>
#include <string>
class LIBSAMPLE_API InjectCode
{
public:
- InjectCode();
+ LIBMINIMAL_DEFAULT_COPY_MOVE(InjectCode)
+
+ InjectCode() noexcept;
virtual ~InjectCode();
- const char* simpleMethod1(int arg0, int arg1);
- const char* simpleMethod2();
- const char* simpleMethod3(int argc, char** argv);
+ const char *simpleMethod1(int arg0, int arg1);
+ const char *simpleMethod2();
+ const char *simpleMethod3(int argc, char **argv);
- const char* overloadedMethod(int argc, char** argv);
- const char* overloadedMethod(int arg0, double arg1);
- const char* overloadedMethod(int arg0, bool arg1);
+ const char *overloadedMethod(int argc, char **argv);
+ const char *overloadedMethod(int arg0, double arg1);
+ const char *overloadedMethod(int arg0, bool arg1);
- virtual int arrayMethod(int count, int* values) const;
+ virtual int arrayMethod(int count, int *values) const;
inline int callArrayMethod(int count, int *values) const { return arrayMethod(count, values); }
- virtual const char* virtualMethod(int arg);
- int sumArrayAndLength(int* values) const;
+ virtual const char *virtualMethod(int arg);
+ int sumArrayAndLength(int *values) const;
+
private:
// This attr is just to retain the memory pointed by all return values,
// So, the memory returned by all methods will be valid until someone call
@@ -33,7 +37,7 @@ private:
std::string m_valueHolder;
template<typename T>
- const char* toStr(const T& value);
+ const char *toStr(const T &value);
};
#endif // INJECTCODE_H
diff --git a/sources/shiboken6/tests/libsample/list.h b/sources/shiboken6/tests/libsample/list.h
index 59a46960e..5e06d2a66 100644
--- a/sources/shiboken6/tests/libsample/list.h
+++ b/sources/shiboken6/tests/libsample/list.h
@@ -18,6 +18,8 @@ class List : public std::list<T>
class IntList : public List<int>
{
public:
+ LIBMINIMAL_DEFAULT_MOVE(IntList)
+
enum CtorEnum {
NoParamsCtor,
IntCtor,
@@ -25,10 +27,13 @@ public:
ListOfIntCtor
};
- inline IntList() : m_ctorUsed(NoParamsCtor) {}
+ inline IntList() noexcept : m_ctorUsed(NoParamsCtor) {}
inline explicit IntList(int val) : m_ctorUsed(IntCtor) { push_back(val); }
- inline IntList(const IntList& lst) : List<int>(lst), m_ctorUsed(CopyCtor) {}
- inline IntList(const List<int>& lst) : List<int>(lst), m_ctorUsed(ListOfIntCtor) {}
+ inline IntList(const List<int> &lst) : List<int>(lst), m_ctorUsed(ListOfIntCtor) {}
+ ~IntList() = default;
+
+ inline IntList(const IntList &lst) : List<int>(lst), m_ctorUsed(CopyCtor) {}
+ IntList &operator=(const IntList &) = default;
inline void append(int v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
@@ -39,6 +44,8 @@ private:
class PointValueList : public List<Point>
{
public:
+ LIBMINIMAL_DEFAULT_MOVE(PointValueList)
+
enum CtorEnum {
NoParamsCtor,
PointCtor,
@@ -46,10 +53,13 @@ public:
ListOfPointValuesCtor
};
- inline PointValueList() : m_ctorUsed(NoParamsCtor) {}
+ inline PointValueList() noexcept : m_ctorUsed(NoParamsCtor) {}
inline explicit PointValueList(Point val) : m_ctorUsed(PointCtor) { push_back(val); }
- inline PointValueList(const PointValueList& lst) : List<Point>(lst), m_ctorUsed(CopyCtor) {}
- inline PointValueList(const List<Point>& lst) : List<Point>(lst), m_ctorUsed(ListOfPointValuesCtor) {}
+ inline PointValueList(const List<Point> &lst) : List<Point>(lst), m_ctorUsed(ListOfPointValuesCtor) {}
+
+ inline PointValueList(const PointValueList &lst) : List<Point>(lst), m_ctorUsed(CopyCtor) {}
+ PointValueList &operator=(const PointValueList &) = default;
+ ~PointValueList() = default;
inline void append(Point v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
@@ -60,6 +70,8 @@ private:
class ObjectTypePtrList : public List<ObjectType*>
{
public:
+ LIBMINIMAL_DEFAULT_MOVE(ObjectTypePtrList)
+
enum CtorEnum {
NoParamsCtor,
ObjectTypeCtor,
@@ -67,15 +79,21 @@ public:
ListOfObjectTypePtrCtor
};
- inline ObjectTypePtrList() : m_ctorUsed(NoParamsCtor) {}
- inline explicit ObjectTypePtrList(ObjectType* val) : m_ctorUsed(ObjectTypeCtor) { push_back(val); }
- inline ObjectTypePtrList(const ObjectTypePtrList& lst) : List<ObjectType*>(lst), m_ctorUsed(CopyCtor) {}
- inline ObjectTypePtrList(const List<ObjectType*>& lst) : List<ObjectType*>(lst), m_ctorUsed(ListOfObjectTypePtrCtor) {}
+ inline ObjectTypePtrList() = default;
+ inline ObjectTypePtrList(const ObjectTypePtrList &lst) :
+ List<ObjectType*>(lst), m_ctorUsed(CopyCtor) {}
+ inline explicit ObjectTypePtrList(ObjectType *val) :
+ m_ctorUsed(ObjectTypeCtor) { push_back(val); }
+ inline ObjectTypePtrList(const List<ObjectType*> &lst) :
+ List<ObjectType*>(lst), m_ctorUsed(ListOfObjectTypePtrCtor) {}
+ ~ObjectTypePtrList() = default;
+
+ ObjectTypePtrList &operator=(const ObjectTypePtrList &) = default;
- inline void append(ObjectType* v) { insert(end(), v); }
+ inline void append(ObjectType *v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
private:
- CtorEnum m_ctorUsed;
+ CtorEnum m_ctorUsed = NoParamsCtor;
};
#endif // LIST_H
diff --git a/sources/shiboken6/tests/libsample/listuser.cpp b/sources/shiboken6/tests/libsample/listuser.cpp
index f68b82b5a..9bb7f7798 100644
--- a/sources/shiboken6/tests/libsample/listuser.cpp
+++ b/sources/shiboken6/tests/libsample/listuser.cpp
@@ -1,20 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <numeric>
-#include <cstdlib>
#include "listuser.h"
-using namespace std;
+#include <numeric>
+#include <cstdlib>
-std::list<int>
-ListUser::callCreateList()
+std::list<int> ListUser::callCreateList()
{
return createList();
}
-std::list<int>
-ListUser::createList()
+ListUser::ListUser() = default;
+ListUser::ListUser(const ListUser &other) = default;
+ListUser::ListUser(ListUser &&other) noexcept = default;
+ListUser &ListUser::operator=(const ListUser &other) = default;
+ListUser &ListUser::operator=(ListUser &&other) noexcept = default;
+ListUser::~ListUser() = default;
+
+std::list<int> ListUser::createList()
{
std::list<int> retval;
for (int i = 0; i < 4; i++)
@@ -22,8 +26,7 @@ ListUser::createList()
return retval;
}
-std::list<Complex>
-ListUser::createComplexList(Complex cpx0, Complex cpx1)
+std::list<Complex> ListUser::createComplexList(Complex cpx0, Complex cpx1)
{
std::list<Complex> retval;
retval.push_back(cpx0);
@@ -31,36 +34,30 @@ ListUser::createComplexList(Complex cpx0, Complex cpx1)
return retval;
}
-double
-ListUser::sumList(std::list<int> vallist)
+double ListUser::sumList(std::list<int> vallist)
{
return std::accumulate(vallist.begin(), vallist.end(), 0.0);
}
-double
-ListUser::sumList(std::list<double> vallist)
+double ListUser::sumList(std::list<double> vallist)
{
return std::accumulate(vallist.begin(), vallist.end(), 0.0);
}
-ListUser::ListOfSomething
-ListUser::listOfPoints(const std::list<Point>& pointlist)
+ListUser::ListOfSomething ListUser::listOfPoints(const std::list<Point> &)
{
return ListOfPoint;
}
-ListUser::ListOfSomething
-ListUser::listOfPoints(const std::list<PointF>& pointlist)
+ListUser::ListOfSomething ListUser::listOfPoints(const std::list<PointF> &)
{
return ListOfPointF;
}
-void
-ListUser::multiplyPointList(PointList& points, double multiplier)
+void ListUser::multiplyPointList(PointList &points, double multiplier)
{
for (auto *point : points) {
point->setX(point->x() * multiplier);
point->setY(point->y() * multiplier);
}
}
-
diff --git a/sources/shiboken6/tests/libsample/listuser.h b/sources/shiboken6/tests/libsample/listuser.h
index 0f564f0e5..96781ed16 100644
--- a/sources/shiboken6/tests/libsample/listuser.h
+++ b/sources/shiboken6/tests/libsample/listuser.h
@@ -4,13 +4,14 @@
#ifndef LISTUSER_H
#define LISTUSER_H
-#include <list>
#include "complex.h"
#include "point.h"
#include "pointf.h"
#include "libsamplemacros.h"
+#include <list>
+
class LIBSAMPLE_API ListUser
{
public:
@@ -21,9 +22,12 @@ public:
ListOfPointF
};
- ListUser() {}
- ListUser(const ListUser& other) : m_lst(other.m_lst) {}
- virtual ~ListUser() {}
+ ListUser();
+ ListUser(const ListUser &other);
+ ListUser(ListUser &&other) noexcept;
+ ListUser &operator=(const ListUser &other);
+ ListUser &operator=(ListUser &&other) noexcept;
+ virtual ~ListUser();
virtual std::list<int> createList();
std::list<int> callCreateList();
@@ -33,13 +37,13 @@ public:
double sumList(std::list<int> vallist);
double sumList(std::list<double> vallist);
- static ListOfSomething listOfPoints(const std::list<Point>& pointlist);
- static ListOfSomething listOfPoints(const std::list<PointF>& pointlist);
+ static ListOfSomething listOfPoints(const std::list<Point> &pointlist);
+ static ListOfSomething listOfPoints(const std::list<PointF> &pointlist);
- static void multiplyPointList(PointList& points, double multiplier);
+ static void multiplyPointList(PointList &points, double multiplier);
inline void setList(std::list<int> lst) { m_lst = lst; }
- inline std::list<int> getList() { return m_lst; }
+ inline std::list<int> getList() const { return m_lst; }
private:
std::list<int> m_lst;
diff --git a/sources/shiboken6/tests/libsample/main.cpp b/sources/shiboken6/tests/libsample/main.cpp
index 9d62e753b..1b44642ae 100644
--- a/sources/shiboken6/tests/libsample/main.cpp
+++ b/sources/shiboken6/tests/libsample/main.cpp
@@ -12,207 +12,197 @@
#include "listuser.h"
#include "samplenamespace.h"
-using namespace std;
-
int
main(int argv, char **argc)
{
- cout << endl;
+ std::cout << std::endl;
Derived derived;
- cout << endl;
+ std::cout << std::endl;
derived.unpureVirtual();
derived.pureVirtual();
derived.callPureVirtual();
- cout << endl;
- Abstract* abs;
- abs = Abstract::createObject();
- cout << "Abstract::createObject(): " << abs << endl << endl;
+ std::cout << std::endl;
+ auto *abs = Abstract::createObject();
+ std::cout << "Abstract::createObject(): " << abs << std::endl << std::endl;
delete abs;
abs = Derived::createObject();
- cout << "Derived::createObject() : ";
+ std::cout << "Derived::createObject() : ";
abs->show();
- cout << endl;
+ std::cout << std::endl;
delete abs;
- cout << endl;
+ std::cout << std::endl;
abs = Derived::createObject();
- cout << "Derived::createObject() : ";
+ std::cout << "Derived::createObject() : ";
abs->show();
- cout << endl;
+ std::cout << std::endl;
delete abs;
- cout << endl;
+ std::cout << std::endl;
- cout << endl << "-----------------------------------------" << endl;
+ std::cout << "\n-----------------------------------------\n";
KinderGarten kg;
- Derived* d[] = { 0, 0, 0 };
+ Derived *d[] = { 0, 0, 0 };
for (int i = 0; i < 3; i++) {
d[i] = new Derived(i);
d[i]->show();
- cout << endl;
+ std::cout << std::endl;
kg.addChild(d[i]);
}
kg.show();
- cout << endl;
+ std::cout << std::endl;
- cout << endl << "* kill child ";
+ std::cout << "\n* kill child ";
d[2]->show();
- cout << " ----------------" << endl;
+ std::cout << " ----------------\n";
kg.killChild(d[2]);
kg.show();
- cout << endl;
+ std::cout << std::endl;
- cout << endl << "* release child ";
+ std::cout << "\n* release child ";
d[1]->show();
- cout << " -------------" << endl;
- Abstract* released = kg.releaseChild(d[1]);
- cout << "released: ";
+ std::cout << " -------------\n";
+ Abstract *released = kg.releaseChild(d[1]);
+ std::cout << "released: ";
released->show();
- cout << endl;
+ std::cout << std::endl;
kg.show();
- cout << endl;
-
- cout << endl << "* kill children ------------------------------------" << endl;
+ std::cout << "\n\n* kill children ------------------------------------\n";
kg.killChildren();
kg.show();
- cout << endl << endl;
-
- cout << "-----------------------------------------" << endl;
+ std::cout << "\n\n-----------------------------------------\n";
ListUser lu;
- cout << "ListUser::createList()" << endl;
+ std::cout << "ListUser::createList()\n";
std::list<int> intlist = lu.createList();
- for (std::list<int>::iterator it = intlist.begin(); it != intlist.end(); it++) {
- cout << "* " << *it << endl;
- }
+ for (std::list<int>::iterator it = intlist.begin(); it != intlist.end(); it++)
+ std::cout << "* " << *it << std::endl;
- cout << "ListUser::createComplexList" << endl;
+ std::cout << "ListUser::createComplexList\n";
std::list<Complex> cpxlist = ListUser::createComplexList(Complex(1.1, 2.2), Complex(3.3, 4.4));
for (std::list<Complex>::iterator it = cpxlist.begin(); it != cpxlist.end(); it++) {
- cout << "* ";
+ std::cout << "* ";
(*it).show();
- cout << endl;
+ std::cout << std::endl;
}
- cout << endl;
-
- cout << "-----------------------------------------" << endl;
- cout << "SampleNamespace" << endl;
-
- cout << "SampleNamespace::RandomNumber: ";
- cout << SampleNamespace::getNumber(SampleNamespace::RandomNumber);
- cout << endl;
- cout << "SampleNamespace::UnixTime: ";
- cout << SampleNamespace::getNumber(SampleNamespace::UnixTime);
- cout << endl;
+ std::cout << "\n-----------------------------------------\n"
+ << "SampleNamespace\n";
+
+ std::cout << "SampleNamespace::RandomNumber: ";
+ std::cout << SampleNamespace::getNumber(SampleNamespace::RandomNumber);
+ std::cout << std::endl;
+ std::cout << "SampleNamespace::UnixTime: ";
+ std::cout << SampleNamespace::getNumber(SampleNamespace::UnixTime);
+ std::cout << std::endl;
double val_d = 1.3;
- cout << "SampleNamespace::powerOfTwo(" << val_d << "): ";
- cout << SampleNamespace::powerOfTwo(val_d) << endl;
+ std::cout << "SampleNamespace::powerOfTwo(" << val_d << "): ";
+ std::cout << SampleNamespace::powerOfTwo(val_d) << std::endl;
int val_i = 7;
- cout << "SampleNamespace::powerOfTwo(" << val_i << "): ";
- cout << SampleNamespace::powerOfTwo(val_i) << endl;
- cout << endl;
+ std::cout << "SampleNamespace::powerOfTwo(" << val_i << "): ";
+ std::cout << SampleNamespace::powerOfTwo(val_i) << std::endl;
+ std::cout << std::endl;
- cout << "-----------------------------------------" << endl;
- cout << "Point" << endl;
+ std::cout << "-----------------------------------------" << std::endl;
+ std::cout << "Point" << std::endl;
Point p1(1.1, 2.2);
- cout << "p1: ";
+ std::cout << "p1: ";
p1.show();
- cout << endl;
+ std::cout << std::endl;
Point p2(3.4, 5.6);
- cout << "p2: ";
+ std::cout << "p2: ";
p2.show();
- cout << endl;
+ std::cout << std::endl;
- cout << "p1 + p2 == ";
+ std::cout << "p1 + p2 == ";
(p1 + p2).show();
- cout << endl;
+ std::cout << std::endl;
- cout << "p1 * 2.0 == ";
+ std::cout << "p1 * 2.0 == ";
(p1 * 2.0).show();
- cout << endl;
+ std::cout << std::endl;
- cout << "1.5 * p2 == ";
+ std::cout << "1.5 * p2 == ";
(1.5 * p2).show();
- cout << endl;
+ std::cout << std::endl;
- cout << "p1: ";
+ std::cout << "p1: ";
p1.show();
- cout << endl << "p2: ";
+ std::cout << std::endl << "p2: ";
p2.show();
- cout << endl << "p1 += p2" << endl;
+ std::cout << std::endl << "p1 += p2" << std::endl;
p1 += p2;
- cout << "p1: ";
+ std::cout << "p1: ";
p1.show();
- cout << endl;
+ std::cout << std::endl;
- cout << "p1 == p2 ? " << ((p1 == p2) ? "true" : "false") << endl;
- cout << "p1 == p1 ? " << ((p1 == p1) ? "true" : "false") << endl;
- cout << "p2 == p2 ? " << ((p2 == p2) ? "true" : "false") << endl;
+ std::cout << "p1 == p2 ? " << ((p1 == p2) ? "true" : "false") << std::endl;
+ std::cout << "p1 == p1 ? " << ((p1 == p1) ? "true" : "false") << std::endl;
+ std::cout << "p2 == p2 ? " << ((p2 == p2) ? "true" : "false") << std::endl;
- cout << "-----------------------------------------" << endl;
- cout << "Size" << endl;
+ std::cout << "-----------------------------------------" << std::endl;
+ std::cout << "Size" << std::endl;
Size s1(2, 2);
- cout << "s1: ";
+ std::cout << "s1: ";
s1.show();
- cout << ", area: " << s1.calculateArea();
- cout << endl;
+ std::cout << ", area: " << s1.calculateArea();
+ std::cout << std::endl;
Size s2(3, 5);
- cout << "s2: ";
+ std::cout << "s2: ";
s2.show();
- cout << ", area: " << s2.calculateArea();
- cout << endl;
-
- cout << endl;
-
- cout << "s1 == s2 ? " << ((s1 == s2) ? "true" : "false") << endl;
- cout << "s1 != s2 ? " << ((s1 != s2) ? "true" : "false") << endl;
-
- cout << "s1 < s2 ? " << ((s1 < s2) ? "true" : "false") << endl;
- cout << "s1 <= s2 ? " << ((s1 <= s2) ? "true" : "false") << endl;
- cout << "s1 > s2 ? " << ((s1 > s2) ? "true" : "false") << endl;
- cout << "s1 >= s2 ? " << ((s1 >= s2) ? "true" : "false") << endl;
-
- cout << "s1 < 10 ? " << ((s1 < 10) ? "true" : "false") << endl;
- cout << "s1 <= 10 ? " << ((s1 <= 10) ? "true" : "false") << endl;
- cout << "s1 > 10 ? " << ((s1 > 10) ? "true" : "false") << endl;
- cout << "s1 >= 10 ? " << ((s1 >= 10) ? "true" : "false") << endl;
- cout << "s2 < 10 ? " << ((s2 < 10) ? "true" : "false") << endl;
- cout << "s2 <= 10 ? " << ((s2 <= 10) ? "true" : "false") << endl;
- cout << "s2 > 10 ? " << ((s2 > 10) ? "true" : "false") << endl;
- cout << "s2 >= 10 ? " << ((s2 >= 10) ? "true" : "false") << endl;
- cout << endl;
-
- cout << "s1: ";
+ std::cout << ", area: " << s2.calculateArea();
+ std::cout << std::endl;
+
+ std::cout << std::endl;
+
+ std::cout << "s1 == s2 ? " << ((s1 == s2) ? "true" : "false") << std::endl;
+ std::cout << "s1 != s2 ? " << ((s1 != s2) ? "true" : "false") << std::endl;
+
+ std::cout << "s1 < s2 ? " << ((s1 < s2) ? "true" : "false") << std::endl;
+ std::cout << "s1 <= s2 ? " << ((s1 <= s2) ? "true" : "false") << std::endl;
+ std::cout << "s1 > s2 ? " << ((s1 > s2) ? "true" : "false") << std::endl;
+ std::cout << "s1 >= s2 ? " << ((s1 >= s2) ? "true" : "false") << std::endl;
+
+ std::cout << "s1 < 10 ? " << ((s1 < 10) ? "true" : "false") << std::endl;
+ std::cout << "s1 <= 10 ? " << ((s1 <= 10) ? "true" : "false") << std::endl;
+ std::cout << "s1 > 10 ? " << ((s1 > 10) ? "true" : "false") << std::endl;
+ std::cout << "s1 >= 10 ? " << ((s1 >= 10) ? "true" : "false") << std::endl;
+ std::cout << "s2 < 10 ? " << ((s2 < 10) ? "true" : "false") << std::endl;
+ std::cout << "s2 <= 10 ? " << ((s2 <= 10) ? "true" : "false") << std::endl;
+ std::cout << "s2 > 10 ? " << ((s2 > 10) ? "true" : "false") << std::endl;
+ std::cout << "s2 >= 10 ? " << ((s2 >= 10) ? "true" : "false") << std::endl;
+ std::cout << std::endl;
+
+ std::cout << "s1: ";
s1.show();
- cout << endl << "s2: ";
+ std::cout << std::endl << "s2: ";
s2.show();
- cout << endl << "s1 += s2" << endl;
+ std::cout << std::endl << "s1 += s2" << std::endl;
s1 += s2;
- cout << "s1: ";
+ std::cout << "s1: ";
s1.show();
- cout << endl;
+ std::cout << std::endl;
- cout << endl;
+ std::cout << std::endl;
- cout << "s1: ";
+ std::cout << "s1: ";
s1.show();
- cout << endl << "s1 *= 2.0" << endl;
+ std::cout << std::endl << "s1 *= 2.0" << std::endl;
s1 *= 2.0;
- cout << "s1: ";
+ std::cout << "s1: ";
s1.show();
- cout << endl;
+ std::cout << std::endl;
- cout << endl;
+ std::cout << std::endl;
return 0;
}
diff --git a/sources/shiboken6/tests/libsample/mapuser.cpp b/sources/shiboken6/tests/libsample/mapuser.cpp
index de96fb40e..40059bbcd 100644
--- a/sources/shiboken6/tests/libsample/mapuser.cpp
+++ b/sources/shiboken6/tests/libsample/mapuser.cpp
@@ -1,44 +1,44 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "mapuser.h"
-using namespace std;
+#include <iostream>
-std::map<std::string, std::pair<Complex, int> >
-MapUser::callCreateMap()
+std::map<std::string, std::pair<Complex, int> > MapUser::callCreateMap()
{
return createMap();
}
-
-std::map<std::string, std::pair<Complex, int> >
-MapUser::createMap()
+std::map<std::string, std::pair<Complex, int> > MapUser::createMap()
{
std::map<std::string, std::pair<Complex, int> > retval;
- std::pair<std::string, std::pair<Complex, int> >
- item0("zero", std::pair<Complex, int>(Complex(1.2, 3.4), 2));
- retval.insert(item0);
+ std::pair<Complex, int> value{Complex(1.2, 3.4), 2};
+ retval.insert({"zero", value});
- std::pair<std::string, std::pair<Complex, int> >
- item1("one", std::pair<Complex, int>(Complex(5.6, 7.8), 3));
- retval.insert(item1);
+ value = {Complex(5.6, 7.8), 3};
+ retval.insert({"one", value});
- std::pair<std::string, std::pair<Complex, int> >
- item2("two", std::pair<Complex, int>(Complex(9.1, 2.3), 5));
- retval.insert(item2);
+ value = {Complex(9.1, 2.3), 5};
+ retval.insert({"two", value});
return retval;
}
-void
-MapUser::showMap(std::map<std::string, int> mapping)
+void MapUser::showMap(std::map<std::string, int> mapping)
+{
+ std::cout << __FUNCTION__ << std::endl;
+ for (const auto &p : mapping)
+ std::cout << p.first << " => " << p.second << std::endl;
+}
+
+void MapUser::pointerToMap(std::map<std::string, std::string> *)
+{
+}
+
+void MapUser::referenceToMap(std::map<std::string, std::string> &)
{
- cout << __FUNCTION__ << endl;
- for (auto it = mapping.begin(), end = mapping.end(); it != end; ++it)
- cout << (*it).first << " => " << (*it).second << endl;
}
std::map<int, std::list<std::list<double> > > MapUser::foo() const
diff --git a/sources/shiboken6/tests/libsample/mapuser.h b/sources/shiboken6/tests/libsample/mapuser.h
index 93cbd0f1e..1677a4bfb 100644
--- a/sources/shiboken6/tests/libsample/mapuser.h
+++ b/sources/shiboken6/tests/libsample/mapuser.h
@@ -4,20 +4,23 @@
#ifndef MAPUSER_H
#define MAPUSER_H
+#include "libsamplemacros.h"
+
+#include "complex.h"
+#include "bytearray.h"
+
#include <map>
#include <list>
#include <utility>
#include <string>
-#include "complex.h"
-#include "bytearray.h"
-
-#include "libsamplemacros.h"
class LIBSAMPLE_API MapUser
{
public:
- MapUser() {}
- virtual ~MapUser() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(MapUser)
+
+ MapUser() noexcept = default;
+ virtual ~MapUser() = default;
virtual std::map<std::string, std::pair<Complex, int> > createMap();
std::map<std::string, std::pair<Complex, int> > callCreateMap();
@@ -28,10 +31,10 @@ public:
inline std::map<std::string, std::list<int> > getMap() { return m_map; }
// Compile test
- static void pointerToMap(std::map<std::string, std::string>* arg) {}
- static void referenceToMap(std::map<std::string, std::string>& arg) {}
+ static void pointerToMap(std::map<std::string, std::string> *arg);
+ static void referenceToMap(std::map<std::string, std::string> &arg);
- inline const std::map<int, ByteArray>& passMapIntValueType(const std::map<int, ByteArray>& arg) { return arg; }
+ inline const std::map<int, ByteArray> &passMapIntValueType(const std::map<int, ByteArray>& arg) { return arg; }
std::map<int, std::list<std::list<double> > > foo() const;
diff --git a/sources/shiboken6/tests/libsample/modelindex.h b/sources/shiboken6/tests/libsample/modelindex.h
index 21980c887..48e1b7de3 100644
--- a/sources/shiboken6/tests/libsample/modelindex.h
+++ b/sources/shiboken6/tests/libsample/modelindex.h
@@ -4,29 +4,30 @@
#ifndef MODELINDEX_H
#define MODELINDEX_H
-#include "libsamplemacros.h"
-
class ModelIndex
{
public:
- ModelIndex() : m_value(0) {}
- ModelIndex(const ModelIndex& other) { m_value = other.m_value; }
+ ModelIndex() = default;
+
inline void setValue(int value) { m_value = value; }
inline int value() const { return m_value; }
- static int getValue(const ModelIndex& index) { return index.value(); }
+ static int getValue(const ModelIndex &index) { return index.value(); }
+
private:
- int m_value;
+ int m_value = 0;
};
class ReferentModelIndex
{
public:
- ReferentModelIndex() {}
- ReferentModelIndex(const ModelIndex& index) : m_index(index) {}
- ReferentModelIndex(const ReferentModelIndex& other) { m_index = other.m_index; }
+ ReferentModelIndex() = default;
+
+ explicit ReferentModelIndex(const ModelIndex &index) : m_index(index) {}
+
inline void setValue(int value) { m_index.setValue(value); }
inline int value() const { return m_index.value(); }
operator const ModelIndex&() const { return m_index; }
+
private:
ModelIndex m_index;
};
@@ -34,14 +35,16 @@ private:
class PersistentModelIndex
{
public:
- PersistentModelIndex() {}
- PersistentModelIndex(const ModelIndex& index) : m_index(index) {}
- PersistentModelIndex(const PersistentModelIndex& other) { m_index = other.m_index; }
+ PersistentModelIndex() = default;
+
+ explicit PersistentModelIndex(const ModelIndex &index) : m_index(index) {}
+
inline void setValue(int value) { m_index.setValue(value); }
inline int value() const { return m_index.value(); }
operator ModelIndex() const { return m_index; }
+
private:
ModelIndex m_index;
};
-#endif
+#endif // MODELINDEX_H
diff --git a/sources/shiboken6/tests/libsample/modifications.cpp b/sources/shiboken6/tests/libsample/modifications.cpp
index 69481443e..6d627c4c1 100644
--- a/sources/shiboken6/tests/libsample/modifications.cpp
+++ b/sources/shiboken6/tests/libsample/modifications.cpp
@@ -1,15 +1,14 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "modifications.h"
#include "objecttype.h"
-using namespace std;
+#include <iostream>
Modifications::Modifications()
+ : m_object(new ObjectType())
{
- m_object = new ObjectType();
m_object->setObjectName("MyObject");
}
@@ -18,30 +17,87 @@ Modifications::~Modifications()
delete m_object;
}
-std::pair<double, double>
-Modifications::pointToPair(Point pt, bool* ok)
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, Point, Point)
+{
+ return Overloaded_ibPP;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, int)
+{
+ return Overloaded_ibii;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, Point)
+{
+ return Overloaded_ibiP;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, bool)
+{
+ return Overloaded_ibib;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, double)
+{
+ return Overloaded_ibid;
+}
+
+void Modifications::argRemoval0(int, bool, int, int)
+{
+}
+
+void Modifications::argRemoval0(int, bool, int, bool)
+{
+}
+
+void Modifications::argRemoval1(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval1(int, bool, int, bool)
+{
+}
+
+void Modifications::argRemoval2(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval3(int, Point, bool, Point, int)
+{
+}
+
+void Modifications::argRemoval4(int, Point, bool, Point, int)
+{
+}
+
+void Modifications::argRemoval5(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval5(int, bool, int, bool)
+{
+}
+
+std::pair<double, double> Modifications::pointToPair(Point pt, bool *ok)
{
std::pair<double, double> retval(pt.x(), pt.y());
*ok = true;
return retval;
}
-double
-Modifications::multiplyPointCoordsPlusValue(bool* ok, Point pt, double value)
+double Modifications::multiplyPointCoordsPlusValue(bool *ok, Point pt, double value)
{
double retval = (pt.x() * pt.y()) + value;
*ok = true;
return retval;
}
-int
-Modifications::doublePlus(int value, int plus)
+int Modifications::doublePlus(int value, int plus)
{
return (2 * value) + plus;
}
-int
-Modifications::power(int base, int exponent)
+int Modifications::power(int base, int exponent)
{
if (exponent == 0)
return 1;
@@ -51,38 +107,32 @@ Modifications::power(int base, int exponent)
return retval;
}
-int
-Modifications::timesTen(int number)
+int Modifications::timesTen(int number)
{
return number * 10;
}
-int
-Modifications::increment(int number)
+int Modifications::increment(int number)
{
return ++number;
}
-void
-Modifications::exclusiveCppStuff()
+void Modifications::exclusiveCppStuff()
{
- cout << __FUNCTION__ << endl;
+ std::cout << __FUNCTION__ << std::endl;
}
-int
-Modifications::cppMultiply(int a, int b)
+int Modifications::cppMultiply(int a, int b)
{
return a * b;
}
-const char*
-Modifications::className()
+const char *Modifications::className()
{
return "Modifications";
}
-Point
-Modifications::sumPointArray(int arraySize, const Point pointArray[])
+Point Modifications::sumPointArray(int arraySize, const Point pointArray[])
{
Point point;
for (int i = 0; i < arraySize; ++i)
@@ -90,21 +140,18 @@ Modifications::sumPointArray(int arraySize, const Point pointArray[])
return point;
}
-int
-Modifications::getSize(const void* data, int size)
+int Modifications::getSize(const void *data, int size)
{
(void)data;
return size;
}
-int
-Modifications::sumPointCoordinates(const Point* point)
+int Modifications::sumPointCoordinates(const Point *point)
{
return point->x() + point->y();
}
-double
-Modifications::differenceOfPointCoordinates(const Point* pt, bool* ok)
+double Modifications::differenceOfPointCoordinates(const Point *pt, bool *ok)
{
if (!pt) {
*ok = false;
@@ -117,8 +164,7 @@ Modifications::differenceOfPointCoordinates(const Point* pt, bool* ok)
return result;
}
-bool
-Modifications::nonConversionRuleForArgumentWithDefaultValue(ObjectType** object)
+bool Modifications::nonConversionRuleForArgumentWithDefaultValue(ObjectType **object)
{
if (object)
*object = m_object;
diff --git a/sources/shiboken6/tests/libsample/modifications.h b/sources/shiboken6/tests/libsample/modifications.h
index 5caabcd9a..5bd1bac47 100644
--- a/sources/shiboken6/tests/libsample/modifications.h
+++ b/sources/shiboken6/tests/libsample/modifications.h
@@ -5,15 +5,18 @@
#define MODIFICATIONS_H
#include "libsamplemacros.h"
-#include <utility>
#include "point.h"
#include "oddbool.h"
+#include <utility>
+
class ObjectType;
class LIBSAMPLE_API Modifications
{
public:
+ LIBMINIMAL_DISABLE_COPY_MOVE(Modifications)
+
Modifications();
virtual ~Modifications();
@@ -33,34 +36,38 @@ public:
// those overloaded methods should be heavily modified
// to push the overload decisor to its limits
- inline OverloadedModFunc overloaded(int a0, bool b0, int c0, double d0) { return Overloaded_ibid; }
- inline OverloadedModFunc overloaded(int a1, bool b1, int c1, bool d1) { return Overloaded_ibib; }
- inline OverloadedModFunc overloaded(int a2, bool b2, int c2, Point d2) { return Overloaded_ibiP; }
- inline OverloadedModFunc overloaded(int a3, bool b3, int c3 = 123, int d3 = 456) { return Overloaded_ibii; }
- inline OverloadedModFunc overloaded(int a4, bool b4, Point c4, Point d4) { return Overloaded_ibPP; }
+ OverloadedModFunc overloaded(int a0, bool b0, int c0, double d0);
+ OverloadedModFunc overloaded(int a1, bool b1, int c1, bool d1);
+ OverloadedModFunc overloaded(int a2, bool b2, int c2, Point d2);
+ OverloadedModFunc overloaded(int a3, bool b3, int c3 = 123, int d3 = 456);
+ OverloadedModFunc overloaded(int a4, bool b4, Point c4, Point d4);
- inline void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456) {}
- inline void argRemoval0(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456);
+ void argRemoval0(int a0, bool a1, int a2, bool a3);
- inline void argRemoval1(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
- inline void argRemoval1(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval1(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
+ void argRemoval1(int a0, bool a1, int a2, bool a3);
- inline void argRemoval2(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval2(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
- inline void argRemoval3(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval3(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4),
+ int a4 = 333);
- inline void argRemoval4(int a0, Point a1, bool a2, Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval4(int a0, Point a1, bool a2, Point a3 = Point(3, 4), int a4 = 333);
- inline void argRemoval5(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
- inline void argRemoval5(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval5(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
+ void argRemoval5(int a0, bool a1, int a2, bool a3);
// 'ok' must be removed and the return value will be changed
// to a tuple (PyObject*) containing the expected result plus
// the 'ok' value as a Python boolean
- std::pair<double, double> pointToPair(Point pt, bool* ok);
+ std::pair<double, double> pointToPair(Point pt, bool *ok);
// same as 'pointToPair' except that this time 'ok' is the first argument
- double multiplyPointCoordsPlusValue(bool* ok, Point pt, double value);
+ double multiplyPointCoordsPlusValue(bool *ok, Point pt, double value);
// completely remove 'plus' from the Python side
int doublePlus(int value, int plus = 0);
@@ -81,24 +88,25 @@ public:
int cppMultiply(int a, int b);
// change the name of this virtual method
- virtual const char* className();
+ virtual const char *className();
Point sumPointArray(int arraySize, const Point pointArray[]);
// Replace 'const void*' by 'ByteArray&'.
- int getSize(const void* data, int size);
+ int getSize(const void *data, int size);
// Mark the argument with a <no-null-pointer/> tag;
// the test implementation must expect point never to be null.
- int sumPointCoordinates(const Point* point);
+ int sumPointCoordinates(const Point *point);
// Modify the return value of a virtual method.
- virtual double differenceOfPointCoordinates(const Point* pt, bool* ok);
- double callDifferenceOfPointCoordinates(const Point* pt, bool* ok) { return differenceOfPointCoordinates(pt, ok); }
+ virtual double differenceOfPointCoordinates(const Point *pt, bool *ok);
+ double callDifferenceOfPointCoordinates(const Point *pt, bool *ok)
+ { return differenceOfPointCoordinates(pt, ok); }
// Sets an ObjectType in the argument and returns true.
bool nonConversionRuleForArgumentWithDefaultValue(ObjectType **object = nullptr);
- ObjectType* getObject() const { return m_object; }
+ ObjectType *getObject() const { return m_object; }
// Inject code with a %CONVERTTOPYTHON that receives an user's primitive type.
static inline OddBool passOddBool(OddBool ob) { return ob; }
@@ -114,7 +122,7 @@ public:
void notifySetAttroCalled();
private:
- ObjectType* m_object;
+ ObjectType *m_object;
TestEnum m_enumValue = TestEnumValue1;
bool m_getAttroCalled = false;
bool m_setAttroCalled = false;
@@ -123,8 +131,10 @@ private:
class LIBSAMPLE_API AbstractModifications : public Modifications
{
public:
- AbstractModifications() {}
- virtual ~AbstractModifications() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(AbstractModifications)
+
+ AbstractModifications() noexcept = default;
+ ~AbstractModifications() override = default;
inline bool invert(bool value) { return !value; }
diff --git a/sources/shiboken6/tests/libsample/modified_constructor.cpp b/sources/shiboken6/tests/libsample/modified_constructor.cpp
index d53815243..c39c97738 100644
--- a/sources/shiboken6/tests/libsample/modified_constructor.cpp
+++ b/sources/shiboken6/tests/libsample/modified_constructor.cpp
@@ -8,8 +8,7 @@ ModifiedConstructor::ModifiedConstructor(int first_arg)
m_stored_value = first_arg;
}
-int
-ModifiedConstructor::retrieveValue()
+int ModifiedConstructor::retrieveValue() const
{
return m_stored_value;
}
diff --git a/sources/shiboken6/tests/libsample/modified_constructor.h b/sources/shiboken6/tests/libsample/modified_constructor.h
index 48cb812a6..a27899f3f 100644
--- a/sources/shiboken6/tests/libsample/modified_constructor.h
+++ b/sources/shiboken6/tests/libsample/modified_constructor.h
@@ -10,8 +10,8 @@ class LIBSAMPLE_API ModifiedConstructor
{
public:
- ModifiedConstructor(int first_arg);
- int retrieveValue();
+ explicit ModifiedConstructor(int first_arg);
+ int retrieveValue() const;
private:
int m_stored_value;
diff --git a/sources/shiboken6/tests/libsample/multiple_derived.cpp b/sources/shiboken6/tests/libsample/multiple_derived.cpp
index 9797a397b..be535c62f 100644
--- a/sources/shiboken6/tests/libsample/multiple_derived.cpp
+++ b/sources/shiboken6/tests/libsample/multiple_derived.cpp
@@ -3,37 +3,22 @@
#include "multiple_derived.h"
-MDerived1::MDerived1() : m_value(100)
-{
-}
+MDerived1::MDerived1() noexcept = default;
-MDerived2::MDerived2() : m_value(200)
-{
-}
+MDerived2::MDerived2() noexcept = default;
-MDerived3::MDerived3() : m_value(3000)
-{
-}
+MDerived3::MDerived3() noexcept = default;
-MDerived4::MDerived4()
-{
-}
+MDerived4::MDerived4() noexcept = default;
-MDerived5::MDerived5()
-{
-}
+MDerived5::MDerived5() noexcept = default;
-MDerived1*
-MDerived1::transformFromBase1(Base1* self)
+MDerived1 *MDerived1::transformFromBase1(Base1 *self)
{
- MDerived1* ptr = dynamic_cast<MDerived1*>(self);
- return ptr;
+ return dynamic_cast<MDerived1*>(self);
}
-MDerived1*
-MDerived1::transformFromBase2(Base2* self)
+MDerived1 *MDerived1::transformFromBase2(Base2 *self)
{
- MDerived1* ptr = dynamic_cast<MDerived1*>(self);
- return ptr;
+ return dynamic_cast<MDerived1*>(self);
}
-
diff --git a/sources/shiboken6/tests/libsample/multiple_derived.h b/sources/shiboken6/tests/libsample/multiple_derived.h
index b91fb34cd..8c2143ed6 100644
--- a/sources/shiboken6/tests/libsample/multiple_derived.h
+++ b/sources/shiboken6/tests/libsample/multiple_derived.h
@@ -5,70 +5,86 @@
#define MDERIVED_H
#include "libsamplemacros.h"
+
#include <string>
class Base1
{
public:
- Base1() : m_value(1) {}
- virtual ~Base1() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base1)
+
+ Base1() noexcept = default;
+ virtual ~Base1() = default;
+
virtual int base1Method() { return m_value; }
virtual void publicMethod() {};
+
private:
- int m_value;
+ int m_value = 1;
};
class Base2
{
public:
- Base2() : m_value(2) {}
- virtual ~Base2() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base2)
+
+ Base2() noexcept = default;
+ virtual ~Base2() = default;
virtual int base2Method() { return m_value; }
+
private:
- int m_value;
+ int m_value = 2;
};
class LIBSAMPLE_API MDerived1 : public Base1, public Base2
{
public:
- MDerived1();
- ~MDerived1() override {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(MDerived1)
+
+ MDerived1() noexcept;
+ ~MDerived1() override = default;
int mderived1Method() { return m_value; }
int base1Method () override { return Base1::base1Method() * 10; }
int base2Method() override { return Base2::base2Method() * 10; }
- inline Base1* castToBase1() { return (Base1*) this; }
- inline Base2* castToBase2() { return (Base2*) this; }
+ inline Base1 *castToBase1() { return (Base1*) this; }
+ inline Base2 *castToBase2() { return (Base2*) this; }
- static MDerived1* transformFromBase1(Base1 *self);
- static MDerived1* transformFromBase2(Base2 *self);
+ static MDerived1 *transformFromBase1(Base1 *self);
+ static MDerived1 *transformFromBase2(Base2 *self);
private:
void publicMethod() override {}
- int m_value;
+ int m_value = 100;
};
class SonOfMDerived1 : public MDerived1
{
public:
- SonOfMDerived1() : m_value(0) {}
- ~SonOfMDerived1() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(SonOfMDerived1)
+
+ SonOfMDerived1() noexcept = default;
+ ~SonOfMDerived1() = default;
- inline MDerived1* castToMDerived1() { return (MDerived1*) this; }
+ inline MDerived1 *castToMDerived1() { return this; }
int sonOfMDerived1Method() { return m_value; }
+
private:
- int m_value;
+ int m_value = 0;
};
class Base3
{
public:
- explicit Base3(int val = 3) : m_value(val) {}
- virtual ~Base3() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base3)
+
+ explicit Base3(int val = 3) noexcept : m_value(val) {}
+ virtual ~Base3() = default;
int base3Method() { return m_value; }
+
private:
int m_value;
};
@@ -76,80 +92,95 @@ private:
class Base4
{
public:
- Base4() : m_value(4) {}
- virtual ~Base4() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base4)
+
+ Base4() noexcept = default;
+ virtual ~Base4() = default;
int base4Method() { return m_value; }
+
private:
- int m_value;
+ int m_value = 4;
};
class Base5
{
public:
- Base5() : m_value(5) {}
- virtual ~Base5() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base5)
+
+ Base5() noexcept = default;
+ virtual ~Base5() = default;
virtual int base5Method() { return m_value; }
+
private:
- int m_value;
+ int m_value = 5;
};
class Base6
{
public:
- Base6() : m_value(6) {}
- virtual ~Base6() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(Base6)
+
+ Base6() noexcept = default;
+ virtual ~Base6() = default;
virtual int base6Method() { return m_value; }
+
private:
- int m_value;
+ int m_value = 6;
};
-
class LIBSAMPLE_API MDerived2 : public Base3, public Base4, public Base5, public Base6
{
public:
- MDerived2();
- virtual ~MDerived2() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(MDerived2)
+
+ MDerived2() noexcept;
+ virtual ~MDerived2() = default;
inline int base4Method() { return Base3::base3Method() * 10; }
inline int mderived2Method() { return m_value; }
- inline Base3* castToBase3() { return (Base3*) this; }
- inline Base4* castToBase4() { return (Base4*) this; }
- inline Base5* castToBase5() { return (Base5*) this; }
- inline Base6* castToBase6() { return (Base6*) this; }
+ inline Base3 *castToBase3() { return this; }
+ inline Base4 *castToBase4() { return this; }
+ inline Base5 *castToBase5() { return this; }
+ inline Base6 *castToBase6() { return this; }
private:
- int m_value;
+ int m_value = 200;
};
class LIBSAMPLE_API MDerived3 : public MDerived1, public MDerived2
{
public:
- MDerived3();
- virtual ~MDerived3() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(MDerived3)
+
+ MDerived3() noexcept;
+ virtual ~MDerived3() = default;
inline virtual int mderived3Method() { return m_value; }
- inline MDerived1* castToMDerived1() { return (MDerived1*) this; }
- inline MDerived2* castToMDerived2() { return (MDerived2*) this; }
+ inline MDerived1 *castToMDerived1() { return this; }
+ inline MDerived2 *castToMDerived2() { return this; }
- inline Base3* castToBase3() { return (Base3*) this; }
+ inline Base3 *castToBase3() { return (Base3*) this; }
private:
- int m_value;
+ int m_value = 3000;
};
class LIBSAMPLE_API MDerived4 : public Base3, public Base4
{
public:
- MDerived4();
- ~MDerived4() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(MDerived4)
+
+ MDerived4() noexcept;
+ ~MDerived4() = default;
inline int mderived4Method() { return 0; }
inline int justDummyMethod() { return m_value; }
- inline Base3* castToBase3() { return (Base3*) this; }
- inline Base4* castToBase4() { return (Base4*) this; }
+ inline Base3 *castToBase3() { return this; }
+ inline Base4 *castToBase4() { return this; }
+
private:
int m_value;
};
@@ -157,14 +188,15 @@ private:
class LIBSAMPLE_API MDerived5 : public Base3, public Base4
{
public:
- MDerived5();
- virtual ~MDerived5() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(MDerived5)
+
+ MDerived5() noexcept;
+ virtual ~MDerived5() = default;
virtual int mderived5Method() { return 0; }
- inline Base3* castToBase3() { return (Base3*) this; }
- inline Base4* castToBase4() { return (Base4*) this; }
+ inline Base3 *castToBase3() { return this; }
+ inline Base4 *castToBase4() { return this; }
};
#endif // MDERIVED_H
-
diff --git a/sources/shiboken6/tests/libsample/noimplicitconversion.h b/sources/shiboken6/tests/libsample/noimplicitconversion.h
index e7d738037..a0b91380b 100644
--- a/sources/shiboken6/tests/libsample/noimplicitconversion.h
+++ b/sources/shiboken6/tests/libsample/noimplicitconversion.h
@@ -13,9 +13,12 @@ class NoImplicitConversion
public:
explicit NoImplicitConversion(int objId) : m_objId(objId) {}
inline int objId() const { return m_objId; }
- inline static int receivesNoImplicitConversionByValue(NoImplicitConversion arg) { return arg.m_objId; }
- inline static int receivesNoImplicitConversionByPointer(NoImplicitConversion* arg) { return arg->m_objId; }
- inline static int receivesNoImplicitConversionByReference(NoImplicitConversion& arg) { return arg.m_objId; }
+ inline static int receivesNoImplicitConversionByValue(NoImplicitConversion arg)
+ { return arg.m_objId; }
+ inline static int receivesNoImplicitConversionByPointer(NoImplicitConversion *arg)
+ { return arg->m_objId; }
+ inline static int receivesNoImplicitConversionByReference(NoImplicitConversion &arg)
+ { return arg.m_objId; }
private:
int m_objId;
};
diff --git a/sources/shiboken6/tests/libsample/nondefaultctor.h b/sources/shiboken6/tests/libsample/nondefaultctor.h
index c410515ad..fa97b8859 100644
--- a/sources/shiboken6/tests/libsample/nondefaultctor.h
+++ b/sources/shiboken6/tests/libsample/nondefaultctor.h
@@ -8,13 +8,16 @@
class NonDefaultCtor
{
- int m_value;
public:
- NonDefaultCtor(int value) : m_value(value)
+ LIBMINIMAL_DEFAULT_COPY_MOVE(NonDefaultCtor)
+
+ explicit NonDefaultCtor(int value) noexcept : m_value(value)
{
}
- inline int value()
+ virtual ~NonDefaultCtor() = default;
+
+ inline int value() const
{
return m_value;
}
@@ -44,7 +47,8 @@ public:
return returnMyselfVirtual();
}
- virtual ~NonDefaultCtor() {}
+private:
+ int m_value;
};
-#endif
+#endif // NONDEFAULTCTOR_H
diff --git a/sources/shiboken6/tests/libsample/nontypetemplate.h b/sources/shiboken6/tests/libsample/nontypetemplate.h
index d3bc7fb8a..e41c21604 100644
--- a/sources/shiboken6/tests/libsample/nontypetemplate.h
+++ b/sources/shiboken6/tests/libsample/nontypetemplate.h
@@ -21,7 +21,7 @@ private:
int m_array[Size];
};
-typedef IntArray<2> IntArray2;
-typedef IntArray<3> IntArray3;
+using IntArray2 = IntArray<2>;
+using IntArray3 = IntArray<3>;
#endif // NONTYPETEMPLATE_H
diff --git a/sources/shiboken6/tests/libsample/null.h b/sources/shiboken6/tests/libsample/null.h
index 9a618095c..945a89fa2 100644
--- a/sources/shiboken6/tests/libsample/null.h
+++ b/sources/shiboken6/tests/libsample/null.h
@@ -8,12 +8,12 @@ class Null
{
public:
Null(bool value) : m_isNull(value) {}
- Null() : m_isNull(false) {}
+ Null() = default;
+
void setIsNull(bool flag) { m_isNull = flag; }
private:
- bool m_isNull;
+ bool m_isNull = false;
};
-#endif // STR_H
-
+#endif // NULL_H
diff --git a/sources/shiboken6/tests/libsample/objectmodel.cpp b/sources/shiboken6/tests/libsample/objectmodel.cpp
index 7ba762d36..56ed86577 100644
--- a/sources/shiboken6/tests/libsample/objectmodel.cpp
+++ b/sources/shiboken6/tests/libsample/objectmodel.cpp
@@ -3,15 +3,22 @@
#include "objectmodel.h"
-void
-ObjectModel::setData(ObjectType* data)
+void ObjectModel::setData(ObjectType *data)
{
m_data = data;
}
-ObjectType*
-ObjectModel::data() const
+ObjectType *ObjectModel::data() const
{
return m_data;
}
+ObjectModel::MethodCalled ObjectModel::receivesObjectTypeFamily(const ObjectModel &)
+{
+ return ObjectModel::ObjectModelCalled;
+}
+
+ObjectModel::MethodCalled ObjectModel::receivesObjectTypeFamily(const ObjectType &)
+{
+ return ObjectModel::ObjectTypeCalled;
+}
diff --git a/sources/shiboken6/tests/libsample/objectmodel.h b/sources/shiboken6/tests/libsample/objectmodel.h
index 6f99c41e0..6d2f97aee 100644
--- a/sources/shiboken6/tests/libsample/objectmodel.h
+++ b/sources/shiboken6/tests/libsample/objectmodel.h
@@ -11,23 +11,21 @@ class LIBSAMPLE_API ObjectModel : public ObjectType
{
public:
explicit ObjectModel(ObjectType *parent = nullptr)
- : ObjectType(parent), m_data(nullptr)
- {}
+ : ObjectType(parent) {}
- void setData(ObjectType* data);
- virtual ObjectType* data() const;
+ void setData(ObjectType *data);
+ virtual ObjectType *data() const;
// The MethodCalled enum and related static methods were created to
// test bug #630 [http://bugs.openbossa.org/show_bug.cgi?id=630]
enum MethodCalled { ObjectTypeCalled, ObjectModelCalled };
- static MethodCalled receivesObjectTypeFamily(const ObjectType& object) { return ObjectModel::ObjectTypeCalled; }
- static MethodCalled receivesObjectTypeFamily(const ObjectModel& object) { return ObjectModel::ObjectModelCalled; }
+ static MethodCalled receivesObjectTypeFamily(const ObjectType &object);
+ static MethodCalled receivesObjectTypeFamily(const ObjectModel &object);
private:
// The model holds only one piece of data.
// (This is just a test after all.)
- ObjectType* m_data;
+ ObjectType *m_data = nullptr;
};
#endif // OBJECTMODEL_H
-
diff --git a/sources/shiboken6/tests/libsample/objecttype.cpp b/sources/shiboken6/tests/libsample/objecttype.cpp
index 03c677104..fa3e7357c 100644
--- a/sources/shiboken6/tests/libsample/objecttype.cpp
+++ b/sources/shiboken6/tests/libsample/objecttype.cpp
@@ -3,44 +3,36 @@
#include "objecttype.h"
#include "objecttypelayout.h"
+
#include <algorithm>
#include <iostream>
#include <string>
#include <assert.h>
-#include <algorithm>
-
-using namespace std;
-
-ObjectType::ObjectType(ObjectType* parent) : m_parent(nullptr), m_layout(nullptr), m_call_id(-1)
+ObjectType::ObjectType(ObjectType *parent)
{
setParent(parent);
}
+ObjectType::ObjectType(ObjectType &&) noexcept = default;
+ObjectType &ObjectType::operator=(ObjectType &&) noexcept = default;
+
ObjectType::~ObjectType()
{
for (auto *o : m_children)
delete o;
}
-ObjectType*
-ObjectType::createWithChild()
+ObjectType *ObjectType::createWithChild()
{
- ObjectType* parent = create();
- ObjectType* child = create();
+ ObjectType *parent = create();
+ ObjectType *child = create();
child->setObjectName("child");
child->setParent(parent);
return parent;
}
-const ObjectType *ObjectType::defaultInstance()
-{
- static ObjectType result;
- return &result;
-}
-
-void
-ObjectType::removeChild(ObjectType* child)
+void ObjectType::removeChild(ObjectType *child)
{
if (!child)
return;
@@ -52,8 +44,7 @@ ObjectType::removeChild(ObjectType* child)
}
}
-ObjectType*
-ObjectType::takeChild(ObjectType* child)
+ObjectType *ObjectType::takeChild(ObjectType *child)
{
if (!child)
return nullptr;
@@ -67,8 +58,7 @@ ObjectType::takeChild(ObjectType* child)
return nullptr;
}
-ObjectType*
-ObjectType::takeChild(const Str& name)
+ObjectType *ObjectType::takeChild(const Str &name)
{
return takeChild(findChild(name));
@@ -82,15 +72,13 @@ ObjectTypeList::iterator ObjectType::findChildByName(const Str &name)
});
}
-ObjectType*
-ObjectType::findChild(const Str& name)
+ObjectType *ObjectType::findChild(const Str &name)
{
auto it = findChildByName(name);
return it != m_children.end() ? *it : nullptr;
}
-void
-ObjectType::killChild(const Str& name)
+void ObjectType::killChild(const Str &name)
{
auto it = findChildByName(name);
if (it != m_children.end()) {
@@ -100,8 +88,7 @@ ObjectType::killChild(const Str& name)
}
}
-void
-ObjectType::setParent(ObjectType* parent)
+void ObjectType::setParent(ObjectType *parent)
{
if (m_parent == parent)
return;
@@ -114,33 +101,28 @@ ObjectType::setParent(ObjectType* parent)
m_parent->m_children.push_back(this);
}
-void
-ObjectType::setObjectName(const Str& name)
+void ObjectType::setObjectName(const Str &name)
{
m_objectName = name;
}
-Str
-ObjectType::objectName() const
+Str ObjectType::objectName() const
{
return m_objectName;
}
-bool
-ObjectType::causeEvent(Event::EventType eventType)
+bool ObjectType::causeEvent(Event::EventType eventType)
{
Event e(eventType);
return event(&e);
}
-bool
-ObjectType::event(Event* event)
+bool ObjectType::event(Event *)
{
return true;
}
-int
-ObjectType::processEvent(ObjectTypeList objects, Event *event)
+int ObjectType::processEvent(ObjectTypeList objects, Event *event)
{
return std::count_if(objects.begin(), objects.end(),
[event] (ObjectType *o) {
@@ -148,38 +130,43 @@ ObjectType::processEvent(ObjectTypeList objects, Event *event)
});
}
-void
-ObjectType::callInvalidateEvent(Event* event)
+void ObjectType::callInvalidateEvent(Event *event)
{
invalidateEvent(event);
}
-void
-ObjectType::setLayout(ObjectTypeLayout* l)
+void ObjectType::invalidateEvent(Event *)
+{
+}
+
+void ObjectType::setLayout(ObjectTypeLayout *l)
{
if (!l) {
- cerr << "[WARNING] ObjectType::setLayout: Cannot set layout to 0." << endl;
+ std::cerr << "[WARNING] ObjectType::setLayout: Cannot set layout to 0.\n";
return;
}
if (layout()) {
if (layout() != l) {
- cerr << "[WARNING] ObjectType::setLayout: Attempting to set ObjectTypeLayout '" << l->objectName().cstring();
- cerr << "' on ObjectType '" << objectName().cstring() << "', which already has a layout." << endl;
+ std::cerr << "[WARNING] ObjectType::setLayout: Attempting to set ObjectTypeLayout '"
+ << l->objectName().cstring()
+ << "' on ObjectType '" << objectName().cstring()
+ << "', which already has a layout.\n";
}
return;
}
- ObjectType* oldParent = l->parent();
+ ObjectType *oldParent = l->parent();
if (oldParent && oldParent != this) {
if (oldParent->isLayoutType()) {
- cerr << "[WARNING] ObjectType::setLayout: Attempting to set ObjectTypeLayout '" << l->objectName().cstring();
- cerr << "' on ObjectType '" << objectName().cstring() << "', when the ObjectTypeLayout already has a parent layout." << endl;
+ std::cerr << "[WARNING] ObjectType::setLayout: Attempting to set ObjectTypeLayout '"
+ << l->objectName().cstring()
+ << "' on ObjectType '" << objectName().cstring()
+ << "', when the ObjectTypeLayout already has a parent layout.\n";
return;
- } else {
- // Steal the layout from an ObjectType parent.
- oldParent->takeLayout();
}
+ // Steal the layout from an ObjectType parent.
+ oldParent->takeLayout();
}
m_layout = l;
@@ -189,9 +176,9 @@ ObjectType::setLayout(ObjectTypeLayout* l)
}
}
-ObjectTypeLayout* ObjectType::takeLayout()
+ObjectTypeLayout *ObjectType::takeLayout()
{
- ObjectTypeLayout* l = layout();
+ ObjectTypeLayout *l = layout();
if (!l)
return nullptr;
m_layout = nullptr;
@@ -199,39 +186,35 @@ ObjectTypeLayout* ObjectType::takeLayout()
return l;
}
-unsigned int
-objectTypeHash(const ObjectType* objectType)
+unsigned int objectTypeHash(const ObjectType *objectType)
{
return reinterpret_cast<std::size_t>(objectType);
}
-unsigned char
-ObjectType::callWithEnum(const Str& prefix, Event::EventType type, unsigned char value){
- return value*value;
+unsigned char ObjectType::callWithEnum(const Str &, Event::EventType, unsigned char value)
+{
+ return value * value;
}
-unsigned char
-ObjectType::callWithEnum(const Str& prefix, unsigned char value) {
+unsigned char ObjectType::callWithEnum(const Str &, unsigned char value)
+{
return value;
}
-void
-ObjectType::setObjectSplittedName(const char*, const Str& prefix, const Str& suffix)
+void ObjectType::setObjectSplittedName(const char *, const Str &prefix, const Str &suffix)
{
std::string result(prefix.cstring());
result += suffix.cstring();
m_objectName = result.c_str();
}
-void
-ObjectType::setObjectNameWithSize(const char*, int size, const Str& name)
+void ObjectType::setObjectNameWithSize(const char *, int size, const Str &name)
{
std::string result(name.cstring(), size);
m_objectName = result.c_str();
}
-void
-ObjectType::setObjectNameWithSize(const Str& name, int size)
+void ObjectType::setObjectNameWithSize(const Str &name, int size)
{
setObjectNameWithSize("", size, name);
}
@@ -251,37 +234,31 @@ int ObjectType::callId() const
return m_call_id;
}
-
void ObjectType::callVirtualCreateChild()
{
- ObjectType* fake_parent = new ObjectType();
- ObjectType* fake_child = createChild(fake_parent);
+ auto *fake_parent = new ObjectType();
+ ObjectType *fake_child = createChild(fake_parent);
assert(fake_child->isPython());
(void)fake_child;
delete fake_parent;
}
-ObjectType* ObjectType::createChild(ObjectType* parent)
+ObjectType *ObjectType::createChild(ObjectType *parent)
{
return new ObjectType(parent);
}
std::size_t ObjectType::createObjectType()
{
- void* addr = new ObjectType();
+ void *addr = new ObjectType();
return (std::size_t) addr;
}
-OtherBase::~OtherBase()
-{
-}
+OtherBase::~OtherBase() = default;
-ObjectTypeDerived::~ObjectTypeDerived()
-{
-}
+ObjectTypeDerived::~ObjectTypeDerived() = default;
-bool
-ObjectTypeDerived::event(Event* event)
+bool ObjectTypeDerived::event(Event *)
{
return true;
}
diff --git a/sources/shiboken6/tests/libsample/objecttype.h b/sources/shiboken6/tests/libsample/objecttype.h
index 798b932f9..498556459 100644
--- a/sources/shiboken6/tests/libsample/objecttype.h
+++ b/sources/shiboken6/tests/libsample/objecttype.h
@@ -4,13 +4,12 @@
#ifndef OBJECTTYPE_H
#define OBJECTTYPE_H
-#include <list>
#include "str.h"
#include "null.h"
#include "libsamplemacros.h"
-#include <stddef.h>
+#include <list>
struct Event
{
@@ -26,11 +25,12 @@ struct Event
Value2
};
- Event(EventType eventType) : m_eventType(eventType) {}
- EventType eventType() { return m_eventType; }
+ explicit Event(EventType eventType) : m_eventType(eventType) {}
+ EventType eventType() const { return m_eventType; }
void setEventType(EventType et) { m_eventType = et; }
void setEventTypeByConstRef(const EventType &et) { m_eventType = et; }
+ void setEventTypeByConstPtr(const EventType *etPtr) { m_eventType = *etPtr; }
private:
EventType m_eventType;
@@ -48,67 +48,72 @@ public:
explicit ObjectType(ObjectType *parent = nullptr);
virtual ~ObjectType();
+ ObjectType(const ObjectType &) = delete;
+ ObjectType &operator=(const ObjectType &) = delete;
+ ObjectType(ObjectType &&) noexcept;
+ ObjectType &operator=(ObjectType &&) noexcept;
// factory method
- inline static ObjectType* create() { return new ObjectType(); }
- static ObjectType* createWithChild();
-
- static const ObjectType *defaultInstance();
-
- void setParent(ObjectType* parent);
- inline ObjectType* parent() const { return m_parent; }
- inline const ObjectTypeList& children() const { return m_children; }
- void killChild(const Str& name);
- void removeChild(ObjectType* child);
- ObjectType* takeChild(ObjectType* child);
- virtual ObjectType* takeChild(const Str& name);
- ObjectType* findChild(const Str& name);
+ inline static ObjectType *create() { return new ObjectType(); }
+ static ObjectType *createWithChild();
+
+ void setParent(ObjectType *parent);
+ inline ObjectType *parent() const { return m_parent; }
+ inline const ObjectTypeList &children() const { return m_children; }
+ void killChild(const Str &name);
+ void removeChild(ObjectType *child);
+ ObjectType *takeChild(ObjectType *child);
+ virtual ObjectType *takeChild(const Str &name);
+ ObjectType *findChild(const Str &name);
Str objectName() const;
- void setObjectName(const Str& name);
+ void setObjectName(const Str &name);
inline Identifier identifier() const { return reinterpret_cast<Identifier>(this); }
bool causeEvent(Event::EventType eventType);
// Returns true if the event is processed.
- virtual bool event(Event* event);
+ virtual bool event(Event *event);
static int processEvent(ObjectTypeList objects, Event *event);
- void callInvalidateEvent(Event* event);
- virtual void invalidateEvent(Event* event) {}
+ void callInvalidateEvent(Event *event);
+ virtual void invalidateEvent(Event *event);
// This nonsense method emulate QWidget.setLayout method
// All layout objects will became children of this object.
- void setLayout(ObjectTypeLayout* layout);
- inline ObjectTypeLayout* layout() const { return m_layout; }
+ void setLayout(ObjectTypeLayout *layout);
+ inline ObjectTypeLayout *layout() const { return m_layout; }
// This method should be reimplemented by ObjectTypeLayout.
virtual bool isLayoutType() { return false; }
- unsigned char callWithEnum(const Str& prefix, Event::EventType type, unsigned char value=80);
- unsigned char callWithEnum(const Str& prefix, unsigned char value=0);
+ unsigned char callWithEnum(const Str &prefix, Event::EventType type,
+ unsigned char value=80);
+ unsigned char callWithEnum(const Str &prefix, unsigned char value=0);
//Functions used in test with named arguments
- void setObjectSplittedName(const char*, const Str& prefix = Str("<unk"), const Str& suffix = Str("nown>"));
- void setObjectNameWithSize(const char*, int size=9, const Str& name = Str("<unknown>"));
- void setObjectNameWithSize(const Str& name = Str("<unknown>"), int size=9);
+ void setObjectSplittedName(const char *, const Str &prefix = Str("<unk"),
+ const Str &suffix = Str("nown>"));
+ void setObjectNameWithSize(const char *, int size=9,
+ const Str &name = Str("<unknown>"));
+ void setObjectNameWithSize(const Str &name = Str("<unknown>"), int size = 9);
//Function used to confuse the generator when two values accept Null as arg
void setObject(ObjectType *);
- void setObject(const Null&);
+ void setObject(const Null &);
int callId() const;
//Function used to create a parent from C++
virtual bool isPython() { return false; }
void callVirtualCreateChild();
- virtual ObjectType* createChild(ObjectType* parent);
+ virtual ObjectType *createChild(ObjectType *parent);
static std::size_t createObjectType();
//return a parent from C++
- ObjectType* getCppParent() {
+ ObjectType *getCppParent() {
if (!m_parent) {
- ObjectType* parent = new ObjectType();
+ ObjectType *parent = new ObjectType();
setParent(parent);
}
return m_parent;
@@ -123,41 +128,39 @@ public:
// nextInFocusChain simply returns the parent to test object cycles; the parent
// may be returned by the QWidget's implementation but isn't always returned
- ObjectType* nextInFocusChain() { return m_parent; }
+ ObjectType *nextInFocusChain() { return m_parent; }
private:
- ObjectType(const ObjectType&);
- ObjectType& operator=(const ObjectType&);
-
- ObjectTypeLayout* takeLayout();
+ ObjectTypeLayout *takeLayout();
ObjectTypeList::iterator findChildByName(const Str &name);
Str m_objectName;
- ObjectType* m_parent;
+ ObjectType *m_parent = nullptr;
ObjectTypeList m_children;
- ObjectTypeLayout* m_layout;
-
-
+ ObjectTypeLayout *m_layout = nullptr;
//used on overload null test
- int m_call_id;
+ int m_call_id = -1;
};
-LIBSAMPLE_API unsigned int objectTypeHash(const ObjectType* objectType);
+LIBSAMPLE_API unsigned int objectTypeHash(const ObjectType *objectType);
class LIBSAMPLE_API OtherBase {
public:
- OtherBase() {};
+ LIBMINIMAL_DISABLE_COPY_MOVE(OtherBase)
+
+ OtherBase() noexcept = default;
virtual ~OtherBase();
};
class LIBSAMPLE_API ObjectTypeDerived: public ObjectType, public OtherBase {
public:
- ObjectTypeDerived(): ObjectType(), OtherBase() {};
+ LIBMINIMAL_DISABLE_COPY_MOVE(ObjectTypeDerived)
- bool event(Event* event) override;
+ ObjectTypeDerived() noexcept = default;
+
+ bool event(Event *event) override;
~ObjectTypeDerived() override;
};
#endif // OBJECTTYPE_H
-
diff --git a/sources/shiboken6/tests/libsample/objecttypebyvalue.h b/sources/shiboken6/tests/libsample/objecttypebyvalue.h
index ff981b517..7b12ff945 100644
--- a/sources/shiboken6/tests/libsample/objecttypebyvalue.h
+++ b/sources/shiboken6/tests/libsample/objecttypebyvalue.h
@@ -3,19 +3,29 @@
#ifndef OBJECTTYPEBYVALUE_H
#define OBJECTTYPEBYVALUE_H
-#include <list>
+
#include "protected.h"
+#include <list>
+
class ObjectTypeByValue
{
public:
- ObjectTypeByValue returnSomeKindOfMe() { return ObjectTypeByValue(); }
- void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe) {}
+ ObjectTypeByValue returnSomeKindOfMe() { return {}; }
+ void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe);
- void acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue> listOfMe) {}
+ void acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue> listOfMe);
// prop used to check for segfaults
ProtectedProperty prop;
};
-#endif
+inline void ObjectTypeByValue::acceptKindOfMeAsValue(ObjectTypeByValue)
+{
+}
+
+inline void ObjectTypeByValue::acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue>)
+{
+}
+
+#endif // OBJECTTYPEBYVALUE_H
diff --git a/sources/shiboken6/tests/libsample/objecttypeholder.cpp b/sources/shiboken6/tests/libsample/objecttypeholder.cpp
index 076023470..c0950d09c 100644
--- a/sources/shiboken6/tests/libsample/objecttypeholder.cpp
+++ b/sources/shiboken6/tests/libsample/objecttypeholder.cpp
@@ -3,14 +3,14 @@
#include "objecttypeholder.h"
-ObjectTypeHolder::ObjectTypeHolder(const char* objectName)
+ObjectTypeHolder::ObjectTypeHolder(const char *objectName)
{
- auto object = new ObjectType();
+ auto *object = new ObjectType();
object->setObjectName(objectName);
m_objectType = object;
}
-ObjectTypeHolder::ObjectTypeHolder(const ObjectType *object) :
+ObjectTypeHolder::ObjectTypeHolder(const ObjectType *object) noexcept :
m_objectType(object)
{
}
@@ -20,14 +20,12 @@ ObjectTypeHolder::~ObjectTypeHolder()
delete m_objectType;
}
-Str
-ObjectTypeHolder::passObjectTypeAsReference(const ObjectType& objectType)
+Str ObjectTypeHolder::passObjectTypeAsReference(const ObjectType &objectType)
{
return objectType.objectName();
}
-Str
-ObjectTypeHolder::callPassObjectTypeAsReference()
+Str ObjectTypeHolder::callPassObjectTypeAsReference()
{
return passObjectTypeAsReference(*m_objectType);
}
diff --git a/sources/shiboken6/tests/libsample/objecttypeholder.h b/sources/shiboken6/tests/libsample/objecttypeholder.h
index f0ddd97b2..190664608 100644
--- a/sources/shiboken6/tests/libsample/objecttypeholder.h
+++ b/sources/shiboken6/tests/libsample/objecttypeholder.h
@@ -11,17 +11,19 @@
class LIBSAMPLE_API ObjectTypeHolder
{
public:
- explicit ObjectTypeHolder(const char* objectName);
- explicit ObjectTypeHolder(const ObjectType *object = ObjectType::defaultInstance());
+ LIBMINIMAL_DISABLE_COPY_MOVE(ObjectTypeHolder)
+
+ explicit ObjectTypeHolder(const char *objectName);
+ explicit ObjectTypeHolder(const ObjectType *object) noexcept;
virtual ~ObjectTypeHolder();
- const ObjectType* getObjecType() { return m_objectType; }
+ const ObjectType *getObjectType() const { return m_objectType; }
- virtual Str passObjectTypeAsReference(const ObjectType& objectType);
+ virtual Str passObjectTypeAsReference(const ObjectType &objectType);
Str callPassObjectTypeAsReference();
private:
const ObjectType *m_objectType;
};
-#endif
+#endif // OBJECTTYPEHOLDER_H
diff --git a/sources/shiboken6/tests/libsample/objecttypelayout.cpp b/sources/shiboken6/tests/libsample/objecttypelayout.cpp
index 2fbd20ccf..3fa02917c 100644
--- a/sources/shiboken6/tests/libsample/objecttypelayout.cpp
+++ b/sources/shiboken6/tests/libsample/objecttypelayout.cpp
@@ -2,17 +2,16 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "objecttypelayout.h"
-#include <iostream>
-using namespace std;
+#include <iostream>
-void ObjectTypeLayout::addObject(ObjectType* obj)
+void ObjectTypeLayout::addObject(ObjectType *obj)
{
if (obj->isLayoutType()) {
- ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(obj);
+ auto *l = reinterpret_cast<ObjectTypeLayout*>(obj);
if (l->parent()) {
- cerr << "[WARNING] ObjectTypeLayout::addObject: layout '" << l->objectName().cstring();
- cerr << "' already has a parent." << endl;
+ std::cerr << "[WARNING] ObjectTypeLayout::addObject: layout '"
+ << l->objectName().cstring() << "' already has a parent.\n";
return;
}
@@ -25,12 +24,12 @@ void ObjectTypeLayout::addObject(ObjectType* obj)
m_objects.push_back(obj);
}
-std::list< ObjectType* > ObjectTypeLayout::objects() const
+std::list<ObjectType*> ObjectTypeLayout::objects() const
{
return m_objects;
}
-void ObjectTypeLayout::reparentChildren(ObjectType* parent)
+void ObjectTypeLayout::reparentChildren(ObjectType *parent)
{
for (auto *o : m_objects) {
if (o->isLayoutType())
@@ -39,4 +38,3 @@ void ObjectTypeLayout::reparentChildren(ObjectType* parent)
o->setParent(parent);
}
}
-
diff --git a/sources/shiboken6/tests/libsample/objecttypelayout.h b/sources/shiboken6/tests/libsample/objecttypelayout.h
index 98eb30946..0aa9fad6e 100644
--- a/sources/shiboken6/tests/libsample/objecttypelayout.h
+++ b/sources/shiboken6/tests/libsample/objecttypelayout.h
@@ -6,6 +6,7 @@
#include "libsamplemacros.h"
#include "objecttype.h"
+
#include <list>
class ObjectType;
@@ -13,19 +14,19 @@ class ObjectType;
class LIBSAMPLE_API ObjectTypeLayout : public ObjectType
{
public:
- void addObject(ObjectType* obj);
+ void addObject(ObjectType *obj);
std::list<ObjectType*> objects() const;
bool isLayoutType() override { return true; }
- inline static ObjectTypeLayout* create() { return new ObjectTypeLayout(); }
+ inline static ObjectTypeLayout *create() { return new ObjectTypeLayout(); }
+
+ ObjectType *takeChild(const Str &name) override { return ObjectType::takeChild(name); }
- ObjectType* takeChild(const Str& name) override { return ObjectType::takeChild(name); }
private:
std::list<ObjectType*> m_objects;
- void reparentChildren(ObjectType* parent);
- friend LIBSAMPLE_API void ObjectType::setLayout(ObjectTypeLayout* l);
+ void reparentChildren(ObjectType *parent);
+ friend LIBSAMPLE_API void ObjectType::setLayout(ObjectTypeLayout *l);
};
#endif // OBJECTTYPELAYOUT_H
-
diff --git a/sources/shiboken6/tests/libsample/objecttypeoperators.cpp b/sources/shiboken6/tests/libsample/objecttypeoperators.cpp
index 05f229a81..c78387a3e 100644
--- a/sources/shiboken6/tests/libsample/objecttypeoperators.cpp
+++ b/sources/shiboken6/tests/libsample/objecttypeoperators.cpp
@@ -7,32 +7,32 @@ ObjectTypeOperators::ObjectTypeOperators(const std::string key) : m_key(key)
{
}
-bool ObjectTypeOperators::operator==(const ObjectTypeOperators& other) const
+bool ObjectTypeOperators::operator==(const ObjectTypeOperators &other) const
{
return m_key == other.m_key;
}
-const ObjectTypeOperators& ObjectTypeOperators::operator<(const ObjectTypeOperators& other) const
+const ObjectTypeOperators &ObjectTypeOperators::operator<(const ObjectTypeOperators &other) const
{
return m_key < other.m_key ? *this : other;
}
-bool operator==(const ObjectTypeOperators* obj, const std::string& str)
+bool operator==(const ObjectTypeOperators *obj, const std::string &str)
{
return obj->key() == str;
}
-bool operator==(const std::string& str, const ObjectTypeOperators* obj)
+bool operator==(const std::string &str, const ObjectTypeOperators *obj)
{
return str == obj->key();
}
-std::string operator+(const ObjectTypeOperators* obj, const std::string& str)
+std::string operator+(const ObjectTypeOperators *obj, const std::string &str)
{
return obj->key() + str;
}
-std::string operator+(const std::string& str, const ObjectTypeOperators* obj)
+std::string operator+(const std::string &str, const ObjectTypeOperators *obj)
{
return str + obj->key();
}
diff --git a/sources/shiboken6/tests/libsample/objecttypeoperators.h b/sources/shiboken6/tests/libsample/objecttypeoperators.h
index b768359a3..6144952ca 100644
--- a/sources/shiboken6/tests/libsample/objecttypeoperators.h
+++ b/sources/shiboken6/tests/libsample/objecttypeoperators.h
@@ -5,32 +5,32 @@
#define OBJECTTYPEOPERATORS_H
#include "libsamplemacros.h"
+
#include <string>
class LIBSAMPLE_API ObjectTypeOperators
{
public:
+ LIBMINIMAL_DISABLE_COPY_MOVE(ObjectTypeOperators)
+
explicit ObjectTypeOperators(const std::string key);
- virtual ~ObjectTypeOperators() {}
+ virtual ~ObjectTypeOperators() = default;
- bool operator==(const ObjectTypeOperators& other) const;
- const ObjectTypeOperators& operator<(const ObjectTypeOperators& other) const;
+ bool operator==(const ObjectTypeOperators &other) const;
+ const ObjectTypeOperators &operator<(const ObjectTypeOperators &other) const;
// chaos!
- virtual void operator>(const ObjectTypeOperators&) { m_key.append("operator>"); }
+ virtual void operator>(const ObjectTypeOperators &) { m_key.append("operator>"); }
std::string key() const { return m_key; }
private:
std::string m_key;
-
- ObjectTypeOperators(ObjectTypeOperators&);
- ObjectTypeOperators& operator=(ObjectTypeOperators&);
};
-LIBSAMPLE_API bool operator==(const ObjectTypeOperators* obj, const std::string& str);
-LIBSAMPLE_API bool operator==(const std::string& str, const ObjectTypeOperators* obj);
-LIBSAMPLE_API std::string operator+(const ObjectTypeOperators* obj, const std::string& str);
-LIBSAMPLE_API std::string operator+(const std::string& str, const ObjectTypeOperators* obj);
+LIBSAMPLE_API bool operator==(const ObjectTypeOperators *obj, const std::string &str);
+LIBSAMPLE_API bool operator==(const std::string &str, const ObjectTypeOperators *obj);
+LIBSAMPLE_API std::string operator+(const ObjectTypeOperators *obj, const std::string &str);
+LIBSAMPLE_API std::string operator+(const std::string &str, const ObjectTypeOperators *obj);
#endif // OBJECTTYPEOPERATORS_H
diff --git a/sources/shiboken6/tests/libsample/objectview.cpp b/sources/shiboken6/tests/libsample/objectview.cpp
index 5717053a7..1b727f88c 100644
--- a/sources/shiboken6/tests/libsample/objectview.cpp
+++ b/sources/shiboken6/tests/libsample/objectview.cpp
@@ -5,25 +5,20 @@
#include "objectmodel.h"
#include "str.h"
-Str
-ObjectView::displayModelData()
+Str ObjectView::displayModelData()
{
if (!m_model)
- return Str("(NULL)");
+ return {"(NULL)"};
return Str("Name: %VAR").arg(m_model->objectName());
}
-void
-ObjectView::modifyModelData(Str& data)
+void ObjectView::modifyModelData(Str &data)
{
if (m_model)
m_model->setObjectName(data);
}
-
-ObjectType*
-ObjectView::getRawModelData()
+ObjectType *ObjectView::getRawModelData()
{
return m_model->data();
}
-
diff --git a/sources/shiboken6/tests/libsample/objectview.h b/sources/shiboken6/tests/libsample/objectview.h
index 1de474ff2..2567deee5 100644
--- a/sources/shiboken6/tests/libsample/objectview.h
+++ b/sources/shiboken6/tests/libsample/objectview.h
@@ -13,21 +13,19 @@ class ObjectModel;
class LIBSAMPLE_API ObjectView : public ObjectType
{
public:
- ObjectView(ObjectModel *model = nullptr, ObjectType *parent = nullptr)
- : ObjectType(parent), m_model(model)
- {}
+ explicit ObjectView(ObjectModel *model = nullptr, ObjectType *parent = nullptr)
+ : ObjectType(parent), m_model(model) {}
- inline void setModel(ObjectModel* model) { m_model = model; }
- inline ObjectModel* model() const { return m_model; }
+ inline void setModel(ObjectModel *model) { m_model = model; }
+ inline ObjectModel *model() const { return m_model; }
Str displayModelData();
- void modifyModelData(Str& data);
+ void modifyModelData(Str &data);
- ObjectType* getRawModelData();
+ ObjectType *getRawModelData();
private:
- ObjectModel* m_model;
+ ObjectModel *m_model;
};
#endif // OBJECTVIEW_H
-
diff --git a/sources/shiboken6/tests/libsample/oddbool.cpp b/sources/shiboken6/tests/libsample/oddbool.cpp
index 06a61f1c2..bc1ee833f 100644
--- a/sources/shiboken6/tests/libsample/oddbool.cpp
+++ b/sources/shiboken6/tests/libsample/oddbool.cpp
@@ -7,7 +7,7 @@ ComparisonTester::ComparisonTester(int v) : m_value(v)
{
}
-ComparisonTester& ComparisonTester::operator=(int v)
+ComparisonTester &ComparisonTester::operator=(int v)
{
m_value = v;
return *this;
diff --git a/sources/shiboken6/tests/libsample/oddbool.h b/sources/shiboken6/tests/libsample/oddbool.h
index a64a05eb3..dd2d32604 100644
--- a/sources/shiboken6/tests/libsample/oddbool.h
+++ b/sources/shiboken6/tests/libsample/oddbool.h
@@ -16,7 +16,7 @@ class OddBool
{
public:
- inline explicit OddBool(bool b) : m_value(b) {}
+ inline explicit OddBool(bool b) noexcept : m_value(b) {}
bool value() const { return m_value; }
inline OddBool operator!() const { return OddBool(!m_value); }
@@ -35,9 +35,11 @@ inline bool operator!=(OddBool b1, OddBool b2) { return (!b1).value() != (!b2).v
class OddBoolUser
{
public:
- OddBoolUser() : m_oddbool(OddBool(false)) {}
- OddBoolUser(const OddBool& oddBool) : m_oddbool(oddBool) {}
- virtual ~OddBoolUser() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(OddBoolUser)
+
+ OddBoolUser() noexcept : m_oddbool(OddBool(false)) {}
+ OddBoolUser(const OddBool &oddBool) : m_oddbool(oddBool) {}
+ virtual ~OddBoolUser() = default;
inline OddBool oddBool() { return m_oddbool; }
inline void setOddBool(OddBool oddBool) { m_oddbool = oddBool; }
@@ -52,7 +54,7 @@ public:
return invertedOddBool();
}
- static inline OddBool getOddBool(const OddBoolUser& oddBoolUser)
+ static inline OddBool getOddBool(const OddBoolUser &oddBoolUser)
{
return oddBoolUser.m_oddbool;
}
diff --git a/sources/shiboken6/tests/libsample/onlycopy.cpp b/sources/shiboken6/tests/libsample/onlycopy.cpp
index 6fa4ad064..981ea88a4 100644
--- a/sources/shiboken6/tests/libsample/onlycopy.cpp
+++ b/sources/shiboken6/tests/libsample/onlycopy.cpp
@@ -11,45 +11,23 @@ public:
int value;
};
-OnlyCopy::OnlyCopy(int value) : d(new OnlyCopyPrivate(value))
+OnlyCopy::OnlyCopy(int value) : d(std::make_shared<OnlyCopyPrivate>(value))
{
-
}
-OnlyCopy::OnlyCopy(OnlyCopyPrivate *dIn) : d(dIn)
-{
-}
-
-OnlyCopy::~OnlyCopy()
-{
- delete d;
-}
-
-OnlyCopy::OnlyCopy(const OnlyCopy& other) : d(new OnlyCopyPrivate(other.value()))
-{
-}
-
-OnlyCopy&
-OnlyCopy::operator=(const OnlyCopy& other)
-{
- d->value = other.d->value;
- return *this;
-}
+OnlyCopy::~OnlyCopy() = default;
int OnlyCopy::value() const
{
return d->value;
}
-OnlyCopy
-FriendOfOnlyCopy::createOnlyCopy(int value)
+OnlyCopy FriendOfOnlyCopy::createOnlyCopy(int value)
{
-
return OnlyCopy(value);
}
-std::list<OnlyCopy>
-FriendOfOnlyCopy::createListOfOnlyCopy(int quantity)
+std::list<OnlyCopy> FriendOfOnlyCopy::createListOfOnlyCopy(int quantity)
{
std::list<OnlyCopy> list;
for (int i = 0; i < quantity; ++i)
diff --git a/sources/shiboken6/tests/libsample/onlycopy.h b/sources/shiboken6/tests/libsample/onlycopy.h
index e7c411a18..7dc3e0069 100644
--- a/sources/shiboken6/tests/libsample/onlycopy.h
+++ b/sources/shiboken6/tests/libsample/onlycopy.h
@@ -5,7 +5,9 @@
#define ONLYCOPYCLASS_H
#include "libsamplemacros.h"
+
#include <list>
+#include <memory>
// These classes simulate a situation found in QWebEngineHistoryItem.
@@ -14,18 +16,20 @@ class OnlyCopyPrivate;
class LIBSAMPLE_API OnlyCopy
{
public:
- OnlyCopy(const OnlyCopy& other);
- OnlyCopy& operator=(const OnlyCopy& other);
+ LIBMINIMAL_DEFAULT_COPY_MOVE(OnlyCopy)
+
~OnlyCopy();
int value() const;
static int getValue(OnlyCopy onlyCopy) { return onlyCopy.value(); }
- static int getValueFromReference(const OnlyCopy& onlyCopy) { return onlyCopy.value(); }
+ static int getValueFromReference(const OnlyCopy &onlyCopy) { return onlyCopy.value(); }
+
private:
- OnlyCopyPrivate *d;
- explicit OnlyCopy(int value);
- explicit OnlyCopy(OnlyCopyPrivate *d); // rejected due to unknown OnlyCopyPrivate
friend class FriendOfOnlyCopy;
+
+ explicit OnlyCopy(int value);
+
+ std::shared_ptr<OnlyCopyPrivate> d;
};
class LIBSAMPLE_API FriendOfOnlyCopy
@@ -35,4 +39,4 @@ public:
static std::list<OnlyCopy> createListOfOnlyCopy(int quantity);
};
-#endif
+#endif // ONLYCOPYCLASS_H
diff --git a/sources/shiboken6/tests/libsample/overload.cpp b/sources/shiboken6/tests/libsample/overload.cpp
index c0dfd820a..34da28e03 100644
--- a/sources/shiboken6/tests/libsample/overload.cpp
+++ b/sources/shiboken6/tests/libsample/overload.cpp
@@ -8,18 +8,196 @@ Overload::FunctionEnum Overload::overloaded()
return Function0;
}
-Overload::FunctionEnum Overload::overloaded(Size* size)
+Overload::FunctionEnum Overload::overloaded(Size *)
{
return Function1;
}
-Overload::FunctionEnum Overload::overloaded(Point* point, ParamEnum param)
+Overload::FunctionEnum Overload::overloaded(Point *, ParamEnum)
{
return Function2;
}
-Overload::FunctionEnum Overload::overloaded(const Point& point)
+Overload::FunctionEnum Overload::overloaded(const Point &)
{
return Function3;
}
+void Overload::differentReturnTypes(ParamEnum)
+{
+
+}
+
+int Overload::differentReturnTypes(ParamEnum, int val)
+{
+ return val;
+}
+
+int Overload::intOverloads(const Point &, double)
+{
+ return 1;
+}
+
+int Overload::intOverloads(int, int)
+{
+ return 2;
+}
+
+int Overload::intOverloads(int, int, double)
+{
+ return 3;
+}
+
+Overload::FunctionEnum Overload::intDoubleOverloads(double, double) const
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::intDoubleOverloads(int, int) const
+{
+ return Function0;
+}
+
+void Overload::singleOverload(Point *)
+{
+}
+
+Overload::FunctionEnum Overload::wrapperIntIntOverloads(const Polygon &, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::wrapperIntIntOverloads(const Point &, int, int)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::strBufferOverloads(const Str &, const char *, bool)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::strBufferOverloads(unsigned char *, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText(const PointF &, const Str &)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText(const Point &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText(const RectF &, const Str &, const Echo &)
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::drawText(const RectF &, int, const Str &)
+{
+ return Function3;
+}
+
+Overload::FunctionEnum Overload::drawText(const Rect &, int, const Str &)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::drawText(int, int, const Str &)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::drawText(int, int, int, int, int, const Str &)
+{
+ return Function6;
+}
+
+Overload::FunctionEnum Overload::drawText2(const PointF &, const Str &)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText2(const Point &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText2(int, int, const Str &)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::drawText2(const RectF &, const Str &, const Echo &)
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::drawText2(const RectF &, int, const Str &)
+{
+ return Function3;
+}
+
+Overload::FunctionEnum Overload::drawText2(const Rect &, int, const Str &)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::drawText2(int, int, int, int, int, const Str &)
+{
+ return Function6;
+}
+
+Overload::FunctionEnum Overload::drawText3(const Str &, const Str &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText3(int, int, int, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText4(int, int, int)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText4(int, int, int, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::acceptSequence()
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const Str &, ParamEnum)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(void *)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const char *const[])
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const Size &)
+{
+ return Function3;
+}
diff --git a/sources/shiboken6/tests/libsample/overload.h b/sources/shiboken6/tests/libsample/overload.h
index 29a6c575f..b640bf7c7 100644
--- a/sources/shiboken6/tests/libsample/overload.h
+++ b/sources/shiboken6/tests/libsample/overload.h
@@ -17,6 +17,8 @@
class LIBSAMPLE_API Overload
{
public:
+ LIBMINIMAL_DISABLE_COPY_MOVE(Overload)
+
enum FunctionEnum {
Function0,
Function1,
@@ -32,69 +34,71 @@ public:
Param1
};
- Overload() {}
- virtual ~Overload() {}
+ Overload() noexcept = default;
+ virtual ~Overload() = default;
FunctionEnum overloaded();
- FunctionEnum overloaded(Size* size);
- FunctionEnum overloaded(Point* point, ParamEnum param);
- FunctionEnum overloaded(const Point& point);
+ FunctionEnum overloaded(Size *size);
+ FunctionEnum overloaded(Point *point, ParamEnum param);
+ FunctionEnum overloaded(const Point &point);
- inline void differentReturnTypes(ParamEnum param = Param0) {}
- inline int differentReturnTypes(ParamEnum param, int val) { return val; }
+ void differentReturnTypes(ParamEnum param = Param0);
+ int differentReturnTypes(ParamEnum param, int val);
- inline int intOverloads(const Point& p, double d) { return 1; }
- inline int intOverloads(int i, int i2) { return 2; }
- inline int intOverloads(int i, int removedArg, double d) { return 3; }
+ int intOverloads(const Point &p, double d);
+ int intOverloads(int i, int i2);
+ int intOverloads(int i, int removedArg, double d);
- inline FunctionEnum intDoubleOverloads(int a0, int a1) const { return Function0; }
- inline FunctionEnum intDoubleOverloads(double a0, double a1) const { return Function1; }
+ FunctionEnum intDoubleOverloads(int a0, int a1) const;
+ FunctionEnum intDoubleOverloads(double a0, double a1) const;
- void singleOverload(Point* x) {}
- Point* singleOverload() {return new Point();}
+ void singleOverload(Point *x);
+ Point *singleOverload() { return new Point(); }
// Similar to QImage::trueMatrix(QMatrix,int,int) and QImage::trueMatrix(QTransform,int,int)
- FunctionEnum wrapperIntIntOverloads(const Point& arg0, int arg1, int arg2) { return Function0; }
- FunctionEnum wrapperIntIntOverloads(const Polygon& arg0, int arg1, int arg2) { return Function1; }
+ FunctionEnum wrapperIntIntOverloads(const Point &arg0, int arg1, int arg2);
+ FunctionEnum wrapperIntIntOverloads(const Polygon &arg0, int arg1, int arg2);
// Similar to QImage constructor
- FunctionEnum strBufferOverloads(const Str &arg0, const char *arg1 = nullptr, bool arg2 = true) { return Function0; }
- FunctionEnum strBufferOverloads(unsigned char* arg0, int arg1) { return Function1; }
+ FunctionEnum strBufferOverloads(const Str &arg0, const char *arg1 = nullptr,
+ bool arg2 = true);
+ FunctionEnum strBufferOverloads(unsigned char *arg0, int arg1);
FunctionEnum strBufferOverloads() { return Function2; }
// Similar to QPainter::drawText(...)
- FunctionEnum drawText(const Point& a0, const Str& a1) { return Function0; }
- FunctionEnum drawText(const PointF& a0, const Str& a1) { return Function1; }
- FunctionEnum drawText(const Rect& a0, int a1, const Str& a2) { return Function2; }
- FunctionEnum drawText(const RectF& a0, int a1, const Str& a2) { return Function3; }
- FunctionEnum drawText(const RectF& a0, const Str& a1, const Echo& a2 = Echo()) { return Function4; }
- FunctionEnum drawText(int a0, int a1, const Str& a2) { return Function5; }
- FunctionEnum drawText(int a0, int a1, int a2, int a3, int a4, const Str& a5) { return Function6; }
+ FunctionEnum drawText(const Point &a0, const Str &a1);
+ FunctionEnum drawText(const PointF &a0, const Str &a1);
+ FunctionEnum drawText(const Rect &a0, int a1, const Str &a2);
+ FunctionEnum drawText(const RectF &a0, int a1, const Str &a2);
+ FunctionEnum drawText(const RectF &a0, const Str &a1, const Echo &a2 = Echo());
+ FunctionEnum drawText(int a0, int a1, const Str &a2);
+ FunctionEnum drawText(int a0, int a1, int a2, int a3, int a4, const Str &a5);
// A variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText2(const Point& a0, const Str& a1) { return Function0; }
- FunctionEnum drawText2(const PointF& a0, const Str& a1) { return Function1; }
- FunctionEnum drawText2(const Rect& a0, int a1, const Str& a2) { return Function2; }
- FunctionEnum drawText2(const RectF& a0, int a1, const Str& a2) { return Function3; }
- FunctionEnum drawText2(const RectF& a0, const Str& a1, const Echo& a2 = Echo()) { return Function4; }
- FunctionEnum drawText2(int a0, int a1, const Str& a2) { return Function5; }
- FunctionEnum drawText2(int a0, int a1, int a2, int a3 = 0, int a4 = 0, const Str& a5 = Str()) { return Function6; }
+ FunctionEnum drawText2(const Point &a0, const Str &a1);
+ FunctionEnum drawText2(const PointF &a0, const Str &a1);
+ FunctionEnum drawText2(const Rect &a0, int a1, const Str &a2);
+ FunctionEnum drawText2(const RectF &a0, int a1, const Str &a2);
+ FunctionEnum drawText2(const RectF &a0, const Str &a1, const Echo &a2 = Echo());
+ FunctionEnum drawText2(int a0, int a1, const Str &a2);
+ FunctionEnum drawText2(int a0, int a1, int a2, int a3 = 0, int a4 = 0,
+ const Str &a5 = Str());
// A simpler variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText3(const Str& a0, const Str& a1, const Str& a2) { return Function0; }
- FunctionEnum drawText3(int a0, int a1, int a2, int a3, int a4) { return Function1; }
+ FunctionEnum drawText3(const Str &a0, const Str &a1, const Str &a2);
+ FunctionEnum drawText3(int a0, int a1, int a2, int a3, int a4);
// Another simpler variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText4(int a0, int a1, int a2) { return Function0; }
- FunctionEnum drawText4(int a0, int a1, int a2, int a3, int a4) { return Function1; }
+ FunctionEnum drawText4(int a0, int a1, int a2);
+ FunctionEnum drawText4(int a0, int a1, int a2, int a3, int a4);
- FunctionEnum acceptSequence() { return Function0; }
- FunctionEnum acceptSequence(int a0, int a1) { return Function1; }
- FunctionEnum acceptSequence(const Str& a0, ParamEnum a1 = Param0) { return Function2; }
- FunctionEnum acceptSequence(const Size& a0) { return Function3; }
+ FunctionEnum acceptSequence();
+ FunctionEnum acceptSequence(int a0, int a1);
+ FunctionEnum acceptSequence(const Str &a0, ParamEnum a1 = Param0);
+ FunctionEnum acceptSequence(const Size &a0);
// The type must be changed to PySequence.
- FunctionEnum acceptSequence(const char* const a0[]) { return Function4; }
- FunctionEnum acceptSequence(void* a0) { return Function5; }
+ FunctionEnum acceptSequence(const char *const a0[]);
+ FunctionEnum acceptSequence(void *a0);
};
class LIBSAMPLE_API Overload2 : public Overload
@@ -115,4 +119,3 @@ private:
};
#endif // OVERLOAD_H
-
diff --git a/sources/shiboken6/tests/libsample/overloadsort.cpp b/sources/shiboken6/tests/libsample/overloadsort.cpp
index 9857f6e86..a9b4b0972 100644
--- a/sources/shiboken6/tests/libsample/overloadsort.cpp
+++ b/sources/shiboken6/tests/libsample/overloadsort.cpp
@@ -3,6 +3,41 @@
#include "overloadsort.h"
+const char *SortedOverload::overload(int)
+{
+ return "int";
+}
+
+const char *SortedOverload::overload(double)
+{
+ return "double";
+}
+
+const char *SortedOverload::overload(ImplicitBase)
+{
+ return "ImplicitBase";
+}
+
+const char *SortedOverload::overload(ImplicitTarget)
+{
+ return "ImplicitTarget";
+}
+
+const char *SortedOverload::overload(const std::list<ImplicitBase> &)
+{
+ return "list(ImplicitBase)";
+}
+
+int SortedOverload::implicit_overload(const ImplicitBase &)
+{
+ return 1;
+}
+
+const char *SortedOverload::overloadDeep(int, ImplicitBase &)
+{
+ return "ImplicitBase";
+}
+
int CustomOverloadSequence::overload(short v) const
{
return v + int(sizeof(v));
diff --git a/sources/shiboken6/tests/libsample/overloadsort.h b/sources/shiboken6/tests/libsample/overloadsort.h
index d0d70b8f3..ee269cc21 100644
--- a/sources/shiboken6/tests/libsample/overloadsort.h
+++ b/sources/shiboken6/tests/libsample/overloadsort.h
@@ -11,52 +11,37 @@
class ImplicitTarget
{
public:
- ImplicitTarget(){}
+ ImplicitTarget() = default;
};
class ImplicitBase
{
public:
- ImplicitBase(){}
- ImplicitBase(const ImplicitTarget &b){}
+ ImplicitBase() = default;
+ ImplicitBase(const ImplicitTarget &b);
};
-class SortedOverload
+inline ImplicitBase::ImplicitBase(const ImplicitTarget &)
{
-public:
-
- inline const char *overload(int x) {
- return "int";
- }
-
- inline const char *overload(double x) {
- return "double";
- }
-
- inline const char *overload(ImplicitBase x) {
- return "ImplicitBase";
- }
-
- inline const char *overload(ImplicitTarget x) {
- return "ImplicitTarget";
- }
+}
- inline const char *overload(const std::list<ImplicitBase> &x) {
- return "list(ImplicitBase)";
- }
-
- inline int implicit_overload(const ImplicitBase &x) {
- return 1;
- }
+class LIBSAMPLE_API SortedOverload
+{
+public:
- inline const char *overloadDeep(int x, ImplicitBase &y) {
- return "ImplicitBase";
- }
+ const char *overload(int x);
+ const char *overload(double x);
+ const char *overload(ImplicitBase x);
+ const char *overload(ImplicitTarget x);
+ const char *overload(const std::list<ImplicitBase> &x);
+ int implicit_overload(const ImplicitBase &x);
- inline const char* pyObjOverload(int, int) { return "int,int"; }
- inline const char* pyObjOverload(unsigned char*, int) { return "PyObject,int"; }
+ const char *overloadDeep(int x, ImplicitBase &y);
+ inline const char *pyObjOverload(int, int) { return "int,int"; }
+ inline const char *pyObjOverload(unsigned char *, int)
+ { return "PyObject,int"; }
};
class LIBSAMPLE_API CustomOverloadSequence
@@ -67,4 +52,3 @@ public:
};
#endif // OVERLOADSORT_H
-
diff --git a/sources/shiboken6/tests/libsample/pairuser.cpp b/sources/shiboken6/tests/libsample/pairuser.cpp
index f1f182c5a..5b7eb4d8c 100644
--- a/sources/shiboken6/tests/libsample/pairuser.cpp
+++ b/sources/shiboken6/tests/libsample/pairuser.cpp
@@ -1,32 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "pairuser.h"
-using namespace std;
-
-std::pair<int, int>
-PairUser::callCreatePair()
+std::pair<int, int> PairUser::callCreatePair()
{
return createPair();
}
-std::pair<int, int>
-PairUser::createPair()
+std::pair<int, int> PairUser::createPair()
{
- return std::pair<int, int>(10, 20);
+ return {10, 20};
}
-std::pair<Complex, Complex>
-PairUser::createComplexPair(Complex cpx0, Complex cpx1)
+std::pair<Complex, Complex> PairUser::createComplexPair(Complex cpx0, Complex cpx1)
{
- return std::pair<Complex, Complex>(cpx0, cpx1);
+ return {cpx0, cpx1};
}
-double
-PairUser::sumPair(std::pair<int, double> pair)
+double PairUser::sumPair(std::pair<int, double> pair)
{
return ((double) pair.first) + pair.second;
}
-
diff --git a/sources/shiboken6/tests/libsample/pairuser.h b/sources/shiboken6/tests/libsample/pairuser.h
index 313651c06..ee51d818e 100644
--- a/sources/shiboken6/tests/libsample/pairuser.h
+++ b/sources/shiboken6/tests/libsample/pairuser.h
@@ -4,16 +4,18 @@
#ifndef PAIRUSER_H
#define PAIRUSER_H
-#include <utility>
+#include "libsamplemacros.h"
#include "complex.h"
-#include "libsamplemacros.h"
+#include <utility>
class LIBSAMPLE_API PairUser
{
public:
- PairUser() {}
- virtual ~PairUser() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(PairUser)
+
+ PairUser() noexcept = default;
+ virtual ~PairUser() = default;
virtual std::pair<int, int> createPair();
std::pair<int, int> callCreatePair();
@@ -26,5 +28,5 @@ public:
private:
std::pair<int, int> m_pair;
};
-#endif // PAIRUSER_H
+#endif // PAIRUSER_H
diff --git a/sources/shiboken6/tests/libsample/pen.cpp b/sources/shiboken6/tests/libsample/pen.cpp
index 877246506..76473a264 100644
--- a/sources/shiboken6/tests/libsample/pen.cpp
+++ b/sources/shiboken6/tests/libsample/pen.cpp
@@ -3,11 +3,11 @@
#include "pen.h"
-Color::Color(SampleNamespace::InValue arg) : m_null(false)
+Color::Color(SampleNamespace::InValue) : m_null(false)
{
}
-Color::Color(unsigned int arg) : m_null(false)
+Color::Color(unsigned int) : m_null(false)
{
}
@@ -45,28 +45,30 @@ void Brush::setColor(const Color &newColor)
m_color = newColor;
}
-Pen::Pen() : m_ctor(EmptyCtor)
-{
-}
+Pen::Pen() = default;
-Pen::Pen(SampleNamespace::Option option) : m_ctor(EnumCtor)
+Pen::Pen(SampleNamespace::Option) : m_ctor(EnumCtor)
{
}
-Pen::Pen(const Color& color) : m_ctor(ColorCtor)
+Pen::Pen(const Color &) : m_ctor(ColorCtor)
{
}
-Pen::Pen(const Pen& pen) : m_ctor(CopyCtor)
+Pen::Pen(const Pen &) : m_ctor(CopyCtor)
{
}
+Pen::Pen(Pen &&) noexcept = default;
+Pen &Pen::operator=(const Pen &pen) = default;
+Pen &Pen::operator=(Pen &&) noexcept = default;
+
int Pen::ctorType()
{
return m_ctor;
}
-void Pen::drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints)
+void Pen::drawLine(int, int, int, int, RenderHints)
{
}
diff --git a/sources/shiboken6/tests/libsample/pen.h b/sources/shiboken6/tests/libsample/pen.h
index 770623519..6f528f0f9 100644
--- a/sources/shiboken6/tests/libsample/pen.h
+++ b/sources/shiboken6/tests/libsample/pen.h
@@ -15,6 +15,7 @@ public:
Color(unsigned int arg);
bool isNull() const;
+
private:
bool m_null = true;
};
@@ -48,8 +49,12 @@ public:
Pen();
Pen(SampleNamespace::Option option);
- Pen(const Color& color);
- Pen(const Pen& pen);
+ Pen(const Color &color);
+ Pen(const Pen &pen);
+ Pen(Pen &&) noexcept;
+ Pen &operator=(const Pen &pen);
+ Pen &operator=(Pen &&) noexcept;
+ ~Pen() = default;
// PYSIDE-1325, default initializer
void drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints = {});
@@ -60,7 +65,7 @@ public:
void setRenderHints(RenderHints h);
private:
- int m_ctor;
+ int m_ctor = EmptyCtor;
RenderHints m_renderHints = None;
};
diff --git a/sources/shiboken6/tests/libsample/photon.cpp b/sources/shiboken6/tests/libsample/photon.cpp
index f98a7c891..2a7f20e33 100644
--- a/sources/shiboken6/tests/libsample/photon.cpp
+++ b/sources/shiboken6/tests/libsample/photon.cpp
@@ -5,21 +5,27 @@
namespace Photon
{
+
const ClassType Base::staticType;
-int callCalculateForValueDuplicatorPointer(ValueDuplicator* value)
+
+int callCalculateForValueDuplicatorPointer(ValueDuplicator *value)
{
return value->calculate();
}
-int callCalculateForValueDuplicatorReference(ValueDuplicator& value)
+
+int callCalculateForValueDuplicatorReference(ValueDuplicator &value)
{
return value.calculate();
}
-int countValueIdentities(const std::list<ValueIdentity>& values)
+
+int countValueIdentities(const std::list<ValueIdentity> &values)
{
return values.size();
}
-int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> >& values)
+
+int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> > &values)
{
return values.size();
}
+
} // namespace Photon
diff --git a/sources/shiboken6/tests/libsample/photon.h b/sources/shiboken6/tests/libsample/photon.h
index 2fbf87d25..2debe47d1 100644
--- a/sources/shiboken6/tests/libsample/photon.h
+++ b/sources/shiboken6/tests/libsample/photon.h
@@ -4,9 +4,10 @@
#ifndef PHOTON_H
#define PHOTON_H
-#include <list>
#include "libsamplemacros.h"
+#include <list>
+
// This namespace and classes simulate
// situations found in Qt's phonon module.
@@ -22,8 +23,11 @@ enum ClassType {
class LIBSAMPLE_API Base
{
public:
- explicit Base(int value) : m_value(value) {}
- virtual ~Base() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Base)
+
+ explicit Base(int value) noexcept : m_value(value) {}
+ virtual ~Base() = default;
+
inline void setValue(int value) { m_value = value; }
inline int value() const { return m_value; }
@@ -42,12 +46,14 @@ class LIBSAMPLE_API TemplateBase : public Base
{
public:
explicit TemplateBase(int value) : Base(value) {}
- inline int multiplicator() const { return (int)CLASS_TYPE; }
- inline int calculate() const { return m_value * ((int)CLASS_TYPE); }
+ inline int multiplicator() const { return int(CLASS_TYPE); }
+ inline int calculate() const { return m_value * (int(CLASS_TYPE)); }
static inline ClassType classType() { return CLASS_TYPE; }
- inline int sumValueUsingPointer(TemplateBase<CLASS_TYPE>* other) const { return m_value + other->m_value; }
- inline int sumValueUsingReference(TemplateBase<CLASS_TYPE>& other) const { return m_value + other.m_value; }
+ inline int sumValueUsingPointer(TemplateBase<CLASS_TYPE> *other) const
+ { return m_value + other->m_value; }
+ inline int sumValueUsingReference(TemplateBase<CLASS_TYPE> &other) const
+ { return m_value + other.m_value; }
inline std::list<TemplateBase<CLASS_TYPE> > getListOfThisTemplateBase()
{
@@ -57,7 +63,8 @@ public:
return objs;
}
- static inline TemplateBase<CLASS_TYPE>* passPointerThrough(TemplateBase<CLASS_TYPE>* obj) { return obj; }
+ static inline TemplateBase<CLASS_TYPE> *passPointerThrough(TemplateBase<CLASS_TYPE> *obj)
+ { return obj; }
ClassType type() const override { return CLASS_TYPE; }
static const ClassType staticType = CLASS_TYPE;
@@ -71,43 +78,31 @@ template class LIBSAMPLE_API TemplateBase<DuplicatorType>;
using ValueIdentity = TemplateBase<IdentityType>;
using ValueDuplicator = TemplateBase<DuplicatorType>;
-LIBSAMPLE_API int callCalculateForValueDuplicatorPointer(ValueDuplicator* value);
-LIBSAMPLE_API int callCalculateForValueDuplicatorReference(ValueDuplicator& value);
-LIBSAMPLE_API int countValueIdentities(const std::list<ValueIdentity>& values);
-LIBSAMPLE_API int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> >& values);
-
-// This simulates an internal error (SEGV) caused by 'noexcept' in
-// boost::intrusive_ptr before support for 'noexcept' was added. The ENTIRE
-// code below is needed to trigger the exception; it isn't seen with just a
-// 'noexcept' following a declaration.
-//
-// NOTE: For reasons that should be fairly obvious, this test unfortunately can
-// only be "run" when building in C++11 mode.
-#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
-# define PHOTON_NOEXCEPT noexcept
-#else
-# define PHOTON_NOEXCEPT
-#endif
+LIBSAMPLE_API int callCalculateForValueDuplicatorPointer(ValueDuplicator *value);
+LIBSAMPLE_API int callCalculateForValueDuplicatorReference(ValueDuplicator &value);
+LIBSAMPLE_API int countValueIdentities(const std::list<ValueIdentity> &values);
+LIBSAMPLE_API int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> > &values);
+
class Pointer
{
public:
- Pointer() PHOTON_NOEXCEPT : px(nullptr) {}
- Pointer(int* p) : px(p) {}
+ Pointer() noexcept = default;
+ explicit Pointer(int *p) : px(p) {}
- void reset() PHOTON_NOEXCEPT { Pointer().swap(*this); }
+ void reset() noexcept { Pointer().swap(*this); }
- int* get() const PHOTON_NOEXCEPT { return px; }
- int& operator*() const { return *px; }
+ int *get() const noexcept { return px; }
+ int &operator*() const { return *px; }
- void swap(Pointer& rhs) PHOTON_NOEXCEPT
+ void swap(Pointer &rhs) noexcept
{
- int* tmp = px;
+ int *tmp = px;
px = rhs.px;
rhs.px = tmp;
}
private:
- int* px;
+ int *px = nullptr;
};
} // namespace Photon
diff --git a/sources/shiboken6/tests/libsample/point.cpp b/sources/shiboken6/tests/libsample/point.cpp
index 397dea3e6..b8630eb1e 100644
--- a/sources/shiboken6/tests/libsample/point.cpp
+++ b/sources/shiboken6/tests/libsample/point.cpp
@@ -1,21 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "point.h"
-using namespace std;
+#include <iostream>
-Point::Point(int x, int y) : m_x(x), m_y(y)
+Point::Point(int x, int y) noexcept : m_x(x), m_y(y)
{
}
-Point::Point(double x, double y) : m_x(x), m_y(y)
+Point::Point(double x, double y) noexcept : m_x(x), m_y(y)
{
}
-void
-Point::midpoint(const Point& other, Point* midpoint) const
+void Point::midpoint(const Point &other, Point *midpoint) const
{
if (!midpoint)
return;
@@ -23,108 +21,91 @@ Point::midpoint(const Point& other, Point* midpoint) const
midpoint->setY((m_y + other.m_y) / 2.0);
}
-Point*
-Point::copy() const
+Point *Point::copy() const
{
- Point* pt = new Point();
+ Point *pt = new Point();
pt->m_x = m_x;
pt->m_y = m_y;
return pt;
}
-void
-Point::show()
+void Point::show() const
{
- cout << "(x: " << m_x << ", y: " << m_y << ")";
+ std::cout << "(x: " << m_x << ", y: " << m_y << ")";
}
-bool
-Point::operator==(const Point& other)
+bool Point::operator==(const Point &other)
{
return m_x == other.m_x && m_y == other.m_y;
}
-Point
-Point::operator+(const Point& other)
+Point Point::operator+(const Point &other)
{
- return Point(m_x + other.m_x, m_y + other.m_y);
+ return {m_x + other.m_x, m_y + other.m_y};
}
-Point
-Point::operator-(const Point& other)
+Point Point::operator-(const Point &other)
{
- return Point(m_x - other.m_x, m_y - other.m_y);
+ return {m_x - other.m_x, m_y - other.m_y};
}
-Point&
-Point::operator+=(Point &other)
+Point &Point::operator+=(Point &other)
{
m_x += other.m_x;
m_y += other.m_y;
return *this;
}
-Point&
-Point::operator-=(Point &other)
+Point &Point::operator-=(Point &other)
{
m_x -= other.m_x;
m_y -= other.m_y;
return *this;
}
-Point
-operator*(const Point& pt, double mult)
+Point operator*(const Point &pt, double mult)
{
return Point(pt.m_x * mult, pt.m_y * mult);
}
-Point
-operator*(const Point& pt, int mult)
+Point operator*(const Point &pt, int mult)
{
- return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult);
+ return {int(pt.m_x) * mult, int(pt.m_y) * mult};
}
-Point
-operator*(double mult, const Point& pt)
+Point operator*(double mult, const Point &pt)
{
- return Point(pt.m_x * mult, pt.m_y * mult);
+ return {pt.m_x * mult, pt.m_y * mult};
}
-Point
-operator*(int mult, const Point& pt)
+Point operator*(int mult, const Point &pt)
{
- return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult);
+ return {int(pt.m_x) * mult, int(pt.m_y) * mult};
}
-Point
-operator-(const Point& pt)
+Point operator-(const Point &pt)
{
- return Point(-pt.m_x, -pt.m_y);
+ return {-pt.m_x, -pt.m_y};
}
-bool
-operator!(const Point& pt)
+bool operator!(const Point &pt)
{
- return (pt.m_x == 0.0 && pt.m_y == 0.0);
+ return pt.m_x == 0.0 && pt.m_y == 0.0;
}
-Point
-Point::operator/(int operand)
+Point Point::operator/(int operand)
{
- return Point(m_x/operand, m_y/operand);
+ return {m_x/operand, m_y/operand};
}
-Complex
-transmutePointIntoComplex(const Point& point)
+Complex transmutePointIntoComplex(const Point &point)
{
Complex cpx(point.x(), point.y());
return cpx;
}
-Point
-transmuteComplexIntoPoint(const Complex& cpx)
+Point transmuteComplexIntoPoint(const Complex &cpx)
{
Point pt(cpx.real(), cpx.imag());
return pt;
}
-
diff --git a/sources/shiboken6/tests/libsample/point.h b/sources/shiboken6/tests/libsample/point.h
index 717658b09..59e0236d5 100644
--- a/sources/shiboken6/tests/libsample/point.h
+++ b/sources/shiboken6/tests/libsample/point.h
@@ -4,17 +4,19 @@
#ifndef POINT_H
#define POINT_H
+#include "libsamplemacros.h"
#include "complex.h"
-#include <utility>
-#include "libsamplemacros.h"
+#include <utility>
class LIBSAMPLE_API Point
{
public:
- Point(int x = 0, int y = 0);
- Point(double x, double y);
- ~Point() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Point)
+
+ Point(int x = 0, int y = 0) noexcept;
+ Point(double x, double y) noexcept;
+ ~Point() = default;
inline double x() const { return m_x; }
inline double y() const { return m_y; }
@@ -27,48 +29,48 @@ public:
// This method could simply return the midpoint,
// but the interesting part of the test is to set the
// result in the pointer argument.
- void midpoint(const Point& other, Point* midpoint) const;
+ void midpoint(const Point &other, Point *midpoint) const;
- Point* copy() const;
+ Point *copy() const;
- inline const Point& getConstReferenceToSelf() const { return *this; }
- inline const Point* getSelf() const { return this; }
+ inline const Point &getConstReferenceToSelf() const { return *this; }
+ inline const Point *getSelf() const { return this; }
// The != operator is not implemented for the purpose of testing
// for the absense of the __ne__ method in the Python binding.
- bool operator==(const Point& other);
+ bool operator==(const Point &other);
- Point operator+(const Point& other);
- Point operator-(const Point& other);
+ Point operator+(const Point &other);
+ Point operator-(const Point &other);
Point operator/(int operand);
- friend LIBSAMPLE_API Point operator*(const Point& pt, double mult);
- friend LIBSAMPLE_API Point operator*(const Point& pt, int mult);
- friend LIBSAMPLE_API Point operator*(double mult, const Point& pt);
- friend LIBSAMPLE_API Point operator*(int mult, const Point& pt);
- friend LIBSAMPLE_API Point operator-(const Point& pt);
- friend LIBSAMPLE_API bool operator!(const Point& pt);
+ friend LIBSAMPLE_API Point operator*(const Point &pt, double mult);
+ friend LIBSAMPLE_API Point operator*(const Point &pt, int mult);
+ friend LIBSAMPLE_API Point operator*(double mult, const Point &pt);
+ friend LIBSAMPLE_API Point operator*(int mult, const Point &pt);
+ friend LIBSAMPLE_API Point operator-(const Point &pt);
+ friend LIBSAMPLE_API bool operator!(const Point &pt);
- Point& operator+=(Point &other);
- Point& operator-=(Point &other);
+ Point &operator+=(Point &other);
+ Point &operator-=(Point &other);
- void show();
+ void show() const;
private:
double m_x;
double m_y;
};
-LIBSAMPLE_API Point operator*(const Point& pt, double mult);
-LIBSAMPLE_API Point operator*(const Point& pt, int mult);
-LIBSAMPLE_API Point operator*(double mult, const Point& pt);
-LIBSAMPLE_API Point operator*(int mult, const Point& pt);
-LIBSAMPLE_API Point operator-(const Point& pt);
-LIBSAMPLE_API bool operator!(const Point& pt);
+LIBSAMPLE_API Point operator*(const Point &pt, double mult);
+LIBSAMPLE_API Point operator*(const Point &pt, int mult);
+LIBSAMPLE_API Point operator*(double mult, const Point &pt);
+LIBSAMPLE_API Point operator*(int mult, const Point &pt);
+LIBSAMPLE_API Point operator-(const Point &pt);
+LIBSAMPLE_API bool operator!(const Point &pt);
-LIBSAMPLE_API Complex transmutePointIntoComplex(const Point& point);
-LIBSAMPLE_API Point transmuteComplexIntoPoint(const Complex& cpx);
+LIBSAMPLE_API Complex transmutePointIntoComplex(const Point &point);
+LIBSAMPLE_API Point transmuteComplexIntoPoint(const Complex &cpx);
-LIBSAMPLE_API Point operator*(const Point& pt, double multiplier);
+LIBSAMPLE_API Point operator*(const Point &pt, double multiplier);
#endif // POINT_H
diff --git a/sources/shiboken6/tests/libsample/pointerholder.h b/sources/shiboken6/tests/libsample/pointerholder.h
index 36ce32205..26f1cf0a6 100644
--- a/sources/shiboken6/tests/libsample/pointerholder.h
+++ b/sources/shiboken6/tests/libsample/pointerholder.h
@@ -9,12 +9,15 @@
class PointerHolder
{
public:
- explicit PointerHolder(void* ptr) : m_pointer(ptr) {}
- ~PointerHolder() {}
- inline void* pointer() const { return m_pointer; }
+ LIBMINIMAL_DEFAULT_COPY_MOVE(PointerHolder)
+
+ explicit PointerHolder(void *ptr) : m_pointer(ptr) {}
+ ~PointerHolder() = default;
+
+ inline void *pointer() const { return m_pointer; }
+
private:
- void* m_pointer;
+ void *m_pointer;
};
#endif // POINTERHOLDER_H
-
diff --git a/sources/shiboken6/tests/libsample/pointf.cpp b/sources/shiboken6/tests/libsample/pointf.cpp
index f68dd0f41..6b39f73a9 100644
--- a/sources/shiboken6/tests/libsample/pointf.cpp
+++ b/sources/shiboken6/tests/libsample/pointf.cpp
@@ -1,21 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "pointf.h"
-using namespace std;
+#include <iostream>
-PointF::PointF(const Point& point) : m_x(point.x()), m_y(point.y())
+PointF::PointF(const Point &point) noexcept : m_x(point.x()), m_y(point.y())
{
}
-PointF::PointF(double x, double y) : m_x(x), m_y(y)
+PointF::PointF(double x, double y) noexcept : m_x(x), m_y(y)
{
}
-void
-PointF::midpoint(const PointF& other, PointF* midpoint) const
+void PointF::midpoint(const PointF &other, PointF *midpoint) const
{
if (!midpoint)
return;
@@ -23,79 +21,66 @@ PointF::midpoint(const PointF& other, PointF* midpoint) const
midpoint->setY((m_y + other.m_y) / 2.0);
}
-void
-PointF::show()
+void PointF::show() const
{
- cout << "(x: " << m_x << ", y: " << m_y << ")";
+ std::cout << "(x: " << m_x << ", y: " << m_y << ")";
}
-bool
-PointF::operator==(const PointF& other)
+bool PointF::operator==(const PointF &other)
{
return m_x == other.m_x && m_y == other.m_y;
}
-PointF
-PointF::operator+(const PointF& other)
+PointF PointF::operator+(const PointF &other)
{
- return PointF(m_x + other.m_x, m_y + other.m_y);
+ return {m_x + other.m_x, m_y + other.m_y};
}
-PointF
-PointF::operator-(const PointF& other)
+PointF PointF::operator-(const PointF &other)
{
- return PointF(m_x - other.m_x, m_y - other.m_y);
+ return {m_x - other.m_x, m_y - other.m_y};
}
-PointF&
-PointF::operator+=(PointF &other)
+PointF &PointF::operator+=(PointF &other)
{
m_x += other.m_x;
m_y += other.m_y;
return *this;
}
-PointF&
-PointF::operator-=(PointF &other)
+PointF &PointF::operator-=(PointF &other)
{
m_x -= other.m_x;
m_y -= other.m_y;
return *this;
}
-PointF
-operator*(const PointF& pt, double mult)
+PointF operator*(const PointF &pt, double mult)
{
- return PointF(pt.m_x * mult, pt.m_y * mult);
+ return {pt.m_x * mult, pt.m_y * mult};
}
-PointF
-operator*(const PointF& pt, int mult)
+PointF operator*(const PointF &pt, int mult)
{
- return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult);
+ return PointF(int(pt.m_x) * mult, int(pt.m_y) * mult);
}
-PointF
-operator*(double mult, const PointF& pt)
+PointF operator*(double mult, const PointF &pt)
{
- return PointF(pt.m_x * mult, pt.m_y * mult);
+ return {pt.m_x * mult, pt.m_y * mult};
}
-PointF
-operator*(int mult, const PointF& pt)
+PointF operator*(int mult, const PointF &pt)
{
- return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult);
+ return PointF(int(pt.m_x) * mult, int(pt.m_y) * mult);
}
-PointF
-operator-(const PointF& pt)
+PointF operator-(const PointF &pt)
{
- return PointF(-pt.m_x, -pt.m_y);
+ return {-pt.m_x, -pt.m_y};
}
-bool
-operator!(const PointF& pt)
+bool operator!(const PointF &pt)
{
- return (pt.m_x == 0.0 && pt.m_y == 0.0);
+ return pt.m_x == 0.0 && pt.m_y == 0.0;
}
-
diff --git a/sources/shiboken6/tests/libsample/pointf.h b/sources/shiboken6/tests/libsample/pointf.h
index 86c8c9d2a..bb50b5c6d 100644
--- a/sources/shiboken6/tests/libsample/pointf.h
+++ b/sources/shiboken6/tests/libsample/pointf.h
@@ -4,17 +4,19 @@
#ifndef POINTF_H
#define POINTF_H
+#include "libsamplemacros.h"
#include "point.h"
-#include <utility>
-#include "libsamplemacros.h"
+#include <utility>
class LIBSAMPLE_API PointF
{
public:
- PointF(const Point& point);
- PointF(double x = 0.0, double y = 0.0);
- ~PointF() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(PointF)
+
+ PointF(const Point &point) noexcept;
+ PointF(double x = 0.0, double y = 0.0) noexcept;
+ ~PointF() noexcept = default;
inline double x() const { return m_x; }
inline double y() const { return m_y; }
@@ -25,39 +27,39 @@ public:
// This method could simply return the midpoint,
// but the interesting part of the test is to set the
// result in the pointer argument.
- void midpoint(const PointF& other, PointF* midpoint) const;
+ void midpoint(const PointF &other, PointF *midpoint) const;
// The != operator is not implemented for the purpose of testing
// for the absence of the __ne__ method in the Python binding.
- bool operator==(const PointF& other);
+ bool operator==(const PointF &other);
- PointF operator+(const PointF& other);
- PointF operator-(const PointF& other);
+ PointF operator+(const PointF &other);
+ PointF operator-(const PointF &other);
- friend LIBSAMPLE_API PointF operator*(const PointF& pt, double mult);
- friend LIBSAMPLE_API PointF operator*(const PointF& pt, int mult);
- friend LIBSAMPLE_API PointF operator*(double mult, const PointF& pt);
- friend LIBSAMPLE_API PointF operator*(int mult, const PointF& pt);
- friend LIBSAMPLE_API PointF operator-(const PointF& pt);
- friend LIBSAMPLE_API bool operator!(const PointF& pt);
+ friend LIBSAMPLE_API PointF operator*(const PointF &pt, double mult);
+ friend LIBSAMPLE_API PointF operator*(const PointF &pt, int mult);
+ friend LIBSAMPLE_API PointF operator*(double mult, const PointF &pt);
+ friend LIBSAMPLE_API PointF operator*(int mult, const PointF &pt);
+ friend LIBSAMPLE_API PointF operator-(const PointF &pt);
+ friend LIBSAMPLE_API bool operator!(const PointF &pt);
- PointF& operator+=(PointF &other);
- PointF& operator-=(PointF &other);
+ PointF &operator+=(PointF &other);
+ PointF &operator-=(PointF &other);
- void show();
+ void show() const;
private:
double m_x;
double m_y;
};
-LIBSAMPLE_API PointF operator*(const PointF& pt, double mult);
-LIBSAMPLE_API PointF operator*(const PointF& pt, int mult);
-LIBSAMPLE_API PointF operator*(double mult, const PointF& pt);
-LIBSAMPLE_API PointF operator*(int mult, const PointF& pt);
-LIBSAMPLE_API PointF operator-(const PointF& pt);
-LIBSAMPLE_API bool operator!(const PointF& pt);
+LIBSAMPLE_API PointF operator*(const PointF &pt, double mult);
+LIBSAMPLE_API PointF operator*(const PointF &pt, int mult);
+LIBSAMPLE_API PointF operator*(double mult, const PointF &pt);
+LIBSAMPLE_API PointF operator*(int mult, const PointF &pt);
+LIBSAMPLE_API PointF operator-(const PointF &pt);
+LIBSAMPLE_API bool operator!(const PointF &pt);
-LIBSAMPLE_API PointF operator*(const PointF& pt, double multiplier);
+LIBSAMPLE_API PointF operator*(const PointF &pt, double multiplier);
#endif // POINTF_H
diff --git a/sources/shiboken6/tests/libsample/polygon.cpp b/sources/shiboken6/tests/libsample/polygon.cpp
index 617ac4f9f..6af597192 100644
--- a/sources/shiboken6/tests/libsample/polygon.cpp
+++ b/sources/shiboken6/tests/libsample/polygon.cpp
@@ -1,34 +1,26 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "polygon.h"
-using namespace std;
-
-Polygon::Polygon(double x, double y)
+Polygon::Polygon(double x, double y) : m_points({Point(x, y)})
{
- m_points.push_back(Point(x, y));
}
-Polygon::Polygon(Point point)
+Polygon::Polygon(Point point) : m_points({point})
{
- m_points.push_back(point);
}
-Polygon::Polygon(PointList points)
+Polygon::Polygon(PointList points) : m_points(points)
{
- m_points = points;
}
-void
-Polygon::addPoint(Point point)
+void Polygon::addPoint(Point point)
{
m_points.push_back(point);
}
-Polygon
-Polygon::doublePolygonScale(Polygon polygon)
+Polygon Polygon::doublePolygonScale(Polygon polygon)
{
Polygon result;
for (const auto &point : polygon.points())
@@ -36,15 +28,12 @@ Polygon::doublePolygonScale(Polygon polygon)
return result;
}
-void
-Polygon::stealOwnershipFromPython(Point* point)
+void Polygon::stealOwnershipFromPython(Point *point)
{
delete point;
}
-void
-Polygon::stealOwnershipFromPython(Polygon* polygon)
+void Polygon::stealOwnershipFromPython(Polygon *polygon)
{
delete polygon;
}
-
diff --git a/sources/shiboken6/tests/libsample/polygon.h b/sources/shiboken6/tests/libsample/polygon.h
index 9a7586d24..2424ddd51 100644
--- a/sources/shiboken6/tests/libsample/polygon.h
+++ b/sources/shiboken6/tests/libsample/polygon.h
@@ -4,38 +4,36 @@
#ifndef POLYGON_H
#define POLYGON_H
-#include <list>
+#include "libsamplemacros.h"
#include "point.h"
-#include "libsamplemacros.h"
+#include <list>
-class LIBSAMPLE_API Polygon
+class LIBSAMPLE_API Polygon // should be moveable
{
public:
using PointList = std::list<Point>;
- Polygon() {}
+ Polygon() noexcept = default;
Polygon(double x, double y);
Polygon(Point point);
Polygon(PointList points);
- ~Polygon() {}
void addPoint(Point point);
- inline const PointList& points() const { return m_points; }
+ inline const PointList &points() const { return m_points; }
// This method intentionally receives and returns copies of a Polygon object.
static Polygon doublePolygonScale(Polygon polygon);
// This method invalidates the argument to be used for Polygon(Point) implicit conversion.
- static void stealOwnershipFromPython(Point* point);
+ static void stealOwnershipFromPython(Point *point);
// This method invalidates the argument to be used in a call to doublePolygonScale(Polygon).
- static void stealOwnershipFromPython(Polygon* polygon);
+ static void stealOwnershipFromPython(Polygon *polygon);
private:
PointList m_points;
};
#endif // POLYGON_H
-
diff --git a/sources/shiboken6/tests/libsample/privatector.h b/sources/shiboken6/tests/libsample/privatector.h
index 9e9f2a1c6..3b38414f8 100644
--- a/sources/shiboken6/tests/libsample/privatector.h
+++ b/sources/shiboken6/tests/libsample/privatector.h
@@ -9,22 +9,34 @@
class PrivateCtor
{
public:
- inline static PrivateCtor* instance()
+ inline static PrivateCtor *instance()
{
static PrivateCtor self;
- self.m_instanciations++;
+ self.m_instantiations++;
return &self;
}
inline int instanceCalls()
{
- return m_instanciations;
+ return m_instantiations;
}
private:
- int m_instanciations;
+ int m_instantiations = 0;
- PrivateCtor() : m_instanciations(0) {}
+ PrivateCtor() = default;
};
-#endif
+class DeletedDefaultCtor
+{
+public:
+ DeletedDefaultCtor() = delete;
+
+ DeletedDefaultCtor(const DeletedDefaultCtor &) = default;
+ DeletedDefaultCtor(DeletedDefaultCtor &&) = default;
+ DeletedDefaultCtor &operator=(const DeletedDefaultCtor &) = default;
+ DeletedDefaultCtor &operator=(DeletedDefaultCtor &&) = default;
+ ~DeletedDefaultCtor() = default;
+};
+
+#endif // PRIVATECTOR_H
diff --git a/sources/shiboken6/tests/libsample/privatedtor.h b/sources/shiboken6/tests/libsample/privatedtor.h
index 84591ccb2..05f18ea53 100644
--- a/sources/shiboken6/tests/libsample/privatedtor.h
+++ b/sources/shiboken6/tests/libsample/privatedtor.h
@@ -9,27 +9,28 @@
class PrivateDtor
{
public:
- inline static PrivateDtor* instance()
+ LIBMINIMAL_DISABLE_COPY_MOVE(PrivateDtor)
+
+ inline static PrivateDtor *instance()
{
static PrivateDtor self;
- self.m_instanciations++;
+ self.m_instantiations++;
return &self;
}
inline int instanceCalls()
{
- return m_instanciations;
+ return m_instantiations;
}
protected:
- inline int protectedInstanceCalls() { return m_instanciations; }
+ inline int protectedInstanceCalls() { return m_instantiations; }
private:
- int m_instanciations;
+ int m_instantiations = 0;
- PrivateDtor() : m_instanciations(0) {}
- PrivateDtor(const PrivateDtor&) {}
- ~PrivateDtor() {}
+ PrivateDtor() noexcept = default;
+ ~PrivateDtor() = default;
};
-#endif
+#endif // PRIVATEDTOR_H
diff --git a/sources/shiboken6/tests/libsample/protected.cpp b/sources/shiboken6/tests/libsample/protected.cpp
index f6cdb3db1..7ab52d22b 100644
--- a/sources/shiboken6/tests/libsample/protected.cpp
+++ b/sources/shiboken6/tests/libsample/protected.cpp
@@ -5,3 +5,12 @@
int ProtectedVirtualDestructor::dtor_called = 0;
+const char *ProtectedNonPolymorphic::dataTypeName(void *) const
+{
+ return "pointer";
+}
+
+const char *ProtectedNonPolymorphic::dataTypeName(int) const
+{
+ return "integer";
+}
diff --git a/sources/shiboken6/tests/libsample/protected.h b/sources/shiboken6/tests/libsample/protected.h
index 1efad9044..059cced5d 100644
--- a/sources/shiboken6/tests/libsample/protected.h
+++ b/sources/shiboken6/tests/libsample/protected.h
@@ -7,26 +7,30 @@
#include "libsamplemacros.h"
#include "objecttype.h"
#include "point.h"
+
#include <string>
#include <list>
class LIBSAMPLE_API ProtectedNonPolymorphic
{
public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(ProtectedNonPolymorphic)
+
explicit ProtectedNonPolymorphic(const char *name) : m_name(name) {}
- ~ProtectedNonPolymorphic() {}
+ ~ProtectedNonPolymorphic() = default;
- inline const char* publicName() { return m_name.c_str(); }
+ inline const char *publicName() { return m_name.c_str(); }
- inline static ProtectedNonPolymorphic* create() { return new ProtectedNonPolymorphic("created"); }
+ inline static ProtectedNonPolymorphic *create()
+ { return new ProtectedNonPolymorphic("created"); }
protected:
- inline const char* protectedName() { return m_name.c_str(); }
+ inline const char *protectedName() { return m_name.c_str(); }
inline int protectedSum(int a0, int a1) { return a0 + a1; }
inline int modifiedProtectedSum(int a0, int a1) { return a0 + a1; }
- inline static const char* protectedStatic() { return "protectedStatic"; }
- inline const char* dataTypeName(void *data = nullptr) const { return "pointer"; }
- inline const char* dataTypeName(int data) const { return "integer"; }
+ inline static const char *protectedStatic() { return "protectedStatic"; }
+ const char *dataTypeName(void *data = nullptr) const;
+ const char *dataTypeName(int data) const;
private:
std::string m_name;
@@ -35,15 +39,18 @@ private:
class LIBSAMPLE_API ProtectedPolymorphic
{
public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(ProtectedPolymorphic)
+
explicit ProtectedPolymorphic(const char *name) : m_name(name) {}
- virtual ~ProtectedPolymorphic() {}
+ virtual ~ProtectedPolymorphic() = default;
- inline static ProtectedPolymorphic* create() { return new ProtectedPolymorphic("created"); }
- inline const char* publicName() { return m_name.c_str(); }
- inline const char* callProtectedName() { return protectedName(); }
+ inline static ProtectedPolymorphic *create()
+ { return new ProtectedPolymorphic("created"); }
+ inline const char *publicName() { return m_name.c_str(); }
+ inline const char *callProtectedName() { return protectedName(); }
protected:
- virtual const char* protectedName() { return m_name.c_str(); }
+ virtual const char *protectedName() { return m_name.c_str(); }
private:
std::string m_name;
@@ -52,22 +59,29 @@ private:
class LIBSAMPLE_API ProtectedPolymorphicDaughter : public ProtectedPolymorphic
{
public:
- explicit ProtectedPolymorphicDaughter(const char *name) : ProtectedPolymorphic(name) {}
- inline static ProtectedPolymorphicDaughter* create() { return new ProtectedPolymorphicDaughter("created"); }
+ explicit ProtectedPolymorphicDaughter(const char *name) :
+ ProtectedPolymorphic(name) {}
+ inline static ProtectedPolymorphicDaughter *create()
+ { return new ProtectedPolymorphicDaughter("created"); }
};
class LIBSAMPLE_API ProtectedPolymorphicGrandDaughter: public ProtectedPolymorphicDaughter
{
public:
- explicit ProtectedPolymorphicGrandDaughter(const char *name) : ProtectedPolymorphicDaughter(name) {}
- inline static ProtectedPolymorphicGrandDaughter* create() { return new ProtectedPolymorphicGrandDaughter("created"); }
+ explicit ProtectedPolymorphicGrandDaughter(const char *name) :
+ ProtectedPolymorphicDaughter(name) {}
+ inline static ProtectedPolymorphicGrandDaughter *create()
+ { return new ProtectedPolymorphicGrandDaughter("created"); }
};
class LIBSAMPLE_API ProtectedVirtualDestructor
{
public:
- ProtectedVirtualDestructor() {}
- inline static ProtectedVirtualDestructor* create() { return new ProtectedVirtualDestructor(); }
+ LIBMINIMAL_DISABLE_COPY_MOVE(ProtectedVirtualDestructor)
+
+ ProtectedVirtualDestructor() noexcept = default;
+ inline static ProtectedVirtualDestructor *create()
+ { return new ProtectedVirtualDestructor(); }
inline static int dtorCalled() { return dtor_called; }
inline static void resetDtorCounter() { dtor_called = 0; }
protected:
@@ -79,8 +93,10 @@ private:
class LIBSAMPLE_API ProtectedEnumClass
{
public:
- ProtectedEnumClass() {}
- virtual ~ProtectedEnumClass() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(ProtectedEnumClass)
+
+ ProtectedEnumClass() noexcept = default;
+ virtual ~ProtectedEnumClass() = default;
enum PublicEnum {
PublicItem0,
PublicItem1
@@ -90,36 +106,33 @@ protected:
ProtectedItem0,
ProtectedItem1
};
- ProtectedEnum callProtectedEnumMethod(ProtectedEnum in) { return protectedEnumMethod(in); }
- inline PublicEnum callPublicEnumMethod(PublicEnum in) { return publicEnumMethod(in); }
+ ProtectedEnum callProtectedEnumMethod(ProtectedEnum in)
+ { return protectedEnumMethod(in); }
+ inline PublicEnum callPublicEnumMethod(PublicEnum in)
+ { return publicEnumMethod(in); }
virtual ProtectedEnum protectedEnumMethod(ProtectedEnum in) { return in; }
virtual PublicEnum publicEnumMethod(PublicEnum in) { return in; }
};
-
class LIBSAMPLE_API ProtectedProperty
{
public:
- ProtectedProperty()
- : protectedValueTypeProperty(Point(0, 0)),
- protectedProperty(0),
- protectedEnumProperty(Event::NO_EVENT),
- protectedValueTypePointerProperty(nullptr),
- protectedObjectTypeProperty(nullptr)
- {}
+ ProtectedProperty() = default;
+
protected:
// This is deliberately the first member to test wrapper registration
// for value type members sharing the same memory address.
- Point protectedValueTypeProperty;
- int protectedProperty;
+ Point protectedValueTypeProperty{0, 0};
+ int protectedProperty = 0;
std::list<int> protectedContainerProperty;
- Event::EventType protectedEnumProperty;
- Point* protectedValueTypePointerProperty;
- ObjectType* protectedObjectTypeProperty;
+ Event::EventType protectedEnumProperty = Event::NO_EVENT;
+ Point *protectedValueTypePointerProperty = nullptr;
+ ObjectType *protectedObjectTypeProperty = nullptr;
};
-LIBSAMPLE_API inline ProtectedProperty* createProtectedProperty() {
+LIBSAMPLE_API inline ProtectedProperty *createProtectedProperty()
+{
return new ProtectedProperty;
}
diff --git a/sources/shiboken6/tests/libsample/rect.h b/sources/shiboken6/tests/libsample/rect.h
index ca3b1912d..53296d26c 100644
--- a/sources/shiboken6/tests/libsample/rect.h
+++ b/sources/shiboken6/tests/libsample/rect.h
@@ -9,53 +9,46 @@
class LIBSAMPLE_API Rect
{
public:
- Rect()
- {
- m_left = m_top = 0;
- m_right = m_bottom = -1;
- }
- Rect(int left, int top, int right, int bottom)
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Rect)
+
+ Rect() noexcept = default;
+ explicit Rect(int left, int top, int right, int bottom) noexcept
: m_left(left), m_top(top), m_right(right), m_bottom(bottom) { }
- ~Rect() {}
+ ~Rect() = default;
+
inline int left() const { return m_left; }
inline int top() const { return m_top; }
inline int right() const { return m_right; }
inline int bottom() const { return m_bottom; }
private:
- int m_left;
- int m_top;
- int m_right;
- int m_bottom;
+ int m_left = 0;
+ int m_top = 0;
+ int m_right = -1;
+ int m_bottom = -1;
};
class LIBSAMPLE_API RectF
{
public:
- RectF()
- {
- m_left = m_top = 0;
- m_right = m_bottom = -1;
- }
- RectF(int left, int top, int right, int bottom)
+ LIBMINIMAL_DEFAULT_COPY_MOVE(RectF)
+
+ RectF() noexcept = default;
+ explicit RectF(int left, int top, int right, int bottom) noexcept
: m_left(left), m_top(top), m_right(right), m_bottom(bottom) { }
- RectF(const Rect& other)
- {
- m_left = other.left();
- m_top = other.top();
- m_right = other.right();
- m_bottom = other.bottom();
- }
- ~RectF() {}
+ RectF(const Rect &other) noexcept :
+ m_left(other.left()), m_top(other.top()),
+ m_right(other.right()), m_bottom(other.bottom()) {}
+ ~RectF() = default;
+
inline double left() const { return m_left; }
inline double top() const { return m_top; }
inline double right() const { return m_right; }
inline double bottom() const { return m_bottom; }
private:
- double m_left;
- double m_top;
- double m_right;
- double m_bottom;
+ double m_left = 0;
+ double m_top = 0;
+ double m_right = -1;
+ double m_bottom = -1;
};
#endif // RECT_H
-
diff --git a/sources/shiboken6/tests/libsample/reference.cpp b/sources/shiboken6/tests/libsample/reference.cpp
index d3c1f882c..29dcfc054 100644
--- a/sources/shiboken6/tests/libsample/reference.cpp
+++ b/sources/shiboken6/tests/libsample/reference.cpp
@@ -1,53 +1,53 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "reference.h"
-using namespace std;
+#include <iostream>
+
+void Reference::show() const
+{
+ std::cout << "Reference.objId: " << m_objId << ", address: " << this;
+}
-void
-Reference::show() const
+Reference &Reference::returnMySecondArg(int, Reference &ref)
{
- cout << "Reference.objId: " << m_objId << ", address: " << this;
+ return ref;
}
-int
-Reference::usesReferenceVirtual(Reference& r, int inc)
+int Reference::usesReferenceVirtual(Reference &r, int inc)
{
return r.m_objId + inc;
}
-int
-Reference::usesConstReferenceVirtual(const Reference& r, int inc)
+int Reference::usesConstReferenceVirtual(const Reference &r, int inc)
{
return r.m_objId + inc;
}
-int
-Reference::callUsesReferenceVirtual(Reference& r, int inc)
+int Reference::callUsesReferenceVirtual(Reference &r, int inc)
{
return usesReferenceVirtual(r, inc);
}
-int
-Reference::callUsesConstReferenceVirtual(const Reference& r, int inc)
+int Reference::callUsesConstReferenceVirtual(const Reference &r, int inc)
{
return usesConstReferenceVirtual(r, inc);
}
-void
-Reference::alterReferenceIdVirtual(Reference& r)
+void Reference::alterReferenceIdVirtual(Reference &r)
{
r.setObjId(r.objId() * Reference::multiplier());
}
-void
-Reference::callAlterReferenceIdVirtual(Reference& r)
+void Reference::callAlterReferenceIdVirtual(Reference &r)
{
alterReferenceIdVirtual(r);
}
-ObjTypeReference::~ObjTypeReference()
+ObjTypeReference::~ObjTypeReference() = default;
+
+ObjTypeReference &ObjTypeReference::returnMySecondArg(int, ObjTypeReference &ref)
{
+ return ref;
}
diff --git a/sources/shiboken6/tests/libsample/reference.h b/sources/shiboken6/tests/libsample/reference.h
index d4b7ce2cf..52818d9ea 100644
--- a/sources/shiboken6/tests/libsample/reference.h
+++ b/sources/shiboken6/tests/libsample/reference.h
@@ -9,34 +9,37 @@
class LIBSAMPLE_API Reference
{
public:
- explicit Reference(int objId = -1)
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Reference)
+
+ explicit Reference(int objId = -1) noexcept
: m_objId(objId) {}
- virtual ~Reference() {}
+ virtual ~Reference() = default;
- inline int objId() { return m_objId; }
+ inline int objId() const { return m_objId; }
inline void setObjId(int objId) { m_objId = objId; }
- inline static int usesReference(Reference& r) { return r.m_objId; }
- inline static int usesConstReference(const Reference& r) { return r.m_objId; }
+ inline static int usesReference(Reference &r) { return r.m_objId; }
+ inline static int usesConstReference(const Reference &r) { return r.m_objId; }
- virtual int usesReferenceVirtual(Reference& r, int inc);
- virtual int usesConstReferenceVirtual(const Reference& r, int inc);
+ virtual int usesReferenceVirtual(Reference &r, int inc);
+ virtual int usesConstReferenceVirtual(const Reference &r, int inc);
- int callUsesReferenceVirtual(Reference& r, int inc);
- int callUsesConstReferenceVirtual(const Reference& r, int inc);
+ int callUsesReferenceVirtual(Reference &r, int inc);
+ int callUsesConstReferenceVirtual(const Reference &r, int inc);
- virtual void alterReferenceIdVirtual(Reference& r);
- void callAlterReferenceIdVirtual(Reference& r);
+ virtual void alterReferenceIdVirtual(Reference &r);
+ void callAlterReferenceIdVirtual(Reference &r);
void show() const;
inline static int multiplier() { return 10; }
- virtual Reference& returnMyFirstArg(Reference& ref) { return ref; }
- virtual Reference& returnMySecondArg(int a, Reference& ref) { return ref; }
+ virtual Reference &returnMyFirstArg(Reference &ref) { return ref; }
+ virtual Reference &returnMySecondArg(int a, Reference &ref);
// nonsense operator to test if Shiboken is ignoring dereference operators.
int operator*() { return m_objId; }
+
private:
int m_objId;
};
@@ -44,13 +47,16 @@ private:
class LIBSAMPLE_API ObjTypeReference
{
public:
- ObjTypeReference() {}
- ObjTypeReference(const ObjTypeReference&) {}
+ LIBMINIMAL_DISABLE_MOVE(ObjTypeReference)
+
+ ObjTypeReference() noexcept = default;
+ ObjTypeReference(const ObjTypeReference &) noexcept = default;
+ ObjTypeReference &operator=(const ObjTypeReference &) = delete;
virtual ~ObjTypeReference();
- virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; }
- virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; }
- virtual ObjTypeReference& justAPureVirtualFunc(ObjTypeReference& ref) = 0;
+
+ virtual ObjTypeReference &returnMyFirstArg(ObjTypeReference &ref) { return ref; }
+ virtual ObjTypeReference &returnMySecondArg(int a, ObjTypeReference &ref);
+ virtual ObjTypeReference &justAPureVirtualFunc(ObjTypeReference &ref) = 0;
};
#endif // REFERENCE_H
-
diff --git a/sources/shiboken6/tests/libsample/removednamespaces.h b/sources/shiboken6/tests/libsample/removednamespaces.h
index 08b28fae5..669f2ebf0 100644
--- a/sources/shiboken6/tests/libsample/removednamespaces.h
+++ b/sources/shiboken6/tests/libsample/removednamespaces.h
@@ -46,4 +46,3 @@ namespace RemovedNamespace3
} // namespace UnremovedNamespace
#endif // REMOVEDNAMESPACE_H
-
diff --git a/sources/shiboken6/tests/libsample/sample.cpp b/sources/shiboken6/tests/libsample/sample.cpp
index 7437a341b..5b5f8588b 100644
--- a/sources/shiboken6/tests/libsample/sample.cpp
+++ b/sources/shiboken6/tests/libsample/sample.cpp
@@ -15,7 +15,7 @@ int sample::value() const
return m_value;
}
-bool operator==(const sample&s1, const sample&s2)
+bool operator==(const sample &s1, const sample &s2)
{
return s1.value() == s2.value();
}
diff --git a/sources/shiboken6/tests/libsample/sample.h b/sources/shiboken6/tests/libsample/sample.h
index 756b4687e..27909571a 100644
--- a/sources/shiboken6/tests/libsample/sample.h
+++ b/sources/shiboken6/tests/libsample/sample.h
@@ -20,9 +20,9 @@ namespace sample
};
// shiboken must not generate richcompare for namespace sample
- LIBSAMPLE_API bool operator==(const sample&s1, const sample&s2);
+ LIBSAMPLE_API bool operator==(const sample &s1, const sample &s2);
const int INT_CONSTANT = 42;
}
-#endif
+#endif // SAMPLE_H
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.cpp b/sources/shiboken6/tests/libsample/samplenamespace.cpp
index bb38e66c9..eae5af2d2 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.cpp
+++ b/sources/shiboken6/tests/libsample/samplenamespace.cpp
@@ -1,12 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
-#include <cstdlib>
-#include <time.h>
#include "samplenamespace.h"
-using namespace std;
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
namespace SampleNamespace
{
@@ -18,91 +17,81 @@ SomeClass::PublicScopedEnum SomeClass::protectedMethodReturningPublicScopedEnum(
return PublicScopedEnum::v1;
}
-OutValue
-enumInEnumOut(InValue in)
+OutValue enumInEnumOut(InValue in)
{
- OutValue retval;
+ auto retval = OutValue(-1);
switch(in) {
- case ZeroIn:
- retval = ZeroOut;
- break;
- case OneIn:
- retval = OneOut;
- break;
- case TwoIn:
- retval = TwoOut;
- break;
- default:
- retval = (OutValue) -1;
+ case ZeroIn:
+ retval = ZeroOut;
+ break;
+ case OneIn:
+ retval = OneOut;
+ break;
+ case TwoIn:
+ retval = TwoOut;
+ break;
+ default:
+ break;
}
return retval;
}
-Option
-enumArgumentWithDefaultValue(Option opt)
+Option enumArgumentWithDefaultValue(Option opt)
{
return opt;
}
-int
-getNumber(Option opt)
+int getNumber(Option opt)
{
int retval;
switch(opt) {
- case RandomNumber:
- retval = rand() % 100;
- break;
- case UnixTime:
- retval = (int) time(nullptr);
- break;
- default:
- retval = 0;
+ case RandomNumber:
+ retval = rand() % 100;
+ break;
+ case UnixTime:
+ retval = int(std::time(nullptr));
+ break;
+ default:
+ retval = 0;
+ break;
}
return retval;
}
-void
-doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format)
+void doSomethingWithArray(const unsigned char *, unsigned int, const char *)
{
// This function does nothing in fact.
// It is here as a dummy copy of QPixmap.loadFromData method
// to check compilation issues, i.e. if it compiles, it's ok.
}
-int
-enumItemAsDefaultValueToIntArgument(int value)
+int enumItemAsDefaultValueToIntArgument(int value)
{
return value;
}
-void
-forceDecisorSideA(ObjectType* object)
+void forceDecisorSideA(ObjectType *)
{
}
-void
-forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object)
+void forceDecisorSideA(const Point &, const Str &, ObjectType *)
{
}
-void
-forceDecisorSideB(int a, ObjectType* object)
+void forceDecisorSideB(int, ObjectType *)
{
}
-void
-forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object)
+void forceDecisorSideB(int, const Point &, const Str &, ObjectType *)
{
}
-double
-passReferenceToValueType(const Point& point, double multiplier)
+double passReferenceToValueType(const Point &point, double multiplier)
{
return (point.x() + point.y()) * multiplier;
}
-int
-passReferenceToObjectType(const ObjectType& obj, int multiplier)
+int passReferenceToObjectType(const ObjectType &obj, int multiplier)
{
return obj.objectName().size() * multiplier;
}
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.h b/sources/shiboken6/tests/libsample/samplenamespace.h
index 711f98c6c..99a0787ee 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.h
+++ b/sources/shiboken6/tests/libsample/samplenamespace.h
@@ -4,12 +4,13 @@
#ifndef SAMPLENAMESPACE_H
#define SAMPLENAMESPACE_H
-#include <list>
#include "libsamplemacros.h"
#include "str.h"
#include "point.h"
#include "objecttype.h"
+#include <list>
+
// Anonymous global enum
enum {
AnonymousGlobalEnum_Value0,
@@ -19,6 +20,25 @@ enum {
namespace SampleNamespace
{
+inline namespace InlineNamespace
+{
+ enum EnumWithinInlineNamespace { EWIN_Value0, EWIN_Value1 };
+
+ class LIBSAMPLE_API ClassWithinInlineNamespace {
+ public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(ClassWithinInlineNamespace)
+
+ ClassWithinInlineNamespace() noexcept = default;
+ ~ClassWithinInlineNamespace() = default;
+
+ void setValue(EnumWithinInlineNamespace v) { m_value = v; }
+ EnumWithinInlineNamespace value() const { return m_value; }
+
+ private:
+ EnumWithinInlineNamespace m_value = EWIN_Value0;
+ };
+} // inline ns
+
enum Option {
None_,
RandomNumber,
@@ -55,7 +75,8 @@ inline double powerOfTwo(double num) {
return num * num;
}
-LIBSAMPLE_API void doSomethingWithArray(const unsigned char *data, unsigned int size, const char *format = nullptr);
+LIBSAMPLE_API void doSomethingWithArray(const unsigned char *data, unsigned int size,
+ const char *format = nullptr);
LIBSAMPLE_API int enumItemAsDefaultValueToIntArgument(int value = ZeroIn);
@@ -70,7 +91,10 @@ public:
class OkThisIsRecursiveEnough
{
public:
- virtual ~OkThisIsRecursiveEnough() {}
+ LIBMINIMAL_DISABLE_COPY_MOVE(OkThisIsRecursiveEnough)
+
+ OkThisIsRecursiveEnough() noexcept = default;
+ virtual ~OkThisIsRecursiveEnough() = default;
enum NiceEnum {
NiceValue1, NiceValue2
};
@@ -79,8 +103,9 @@ public:
NiceClassValue1, NiceClassValue2
};
- inline int someMethod(SomeInnerClass*) { return 0; }
- virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; }
+ inline int someMethod(SomeInnerClass *) { return 0; }
+ virtual OkThisIsRecursiveEnough *someVirtualMethod(OkThisIsRecursiveEnough *arg)
+ { return arg; }
};
protected:
enum ProtectedEnum {
@@ -100,7 +125,8 @@ protected:
PublicScopedEnum protectedMethodReturningPublicScopedEnum() const;
};
-LIBSAMPLE_API inline int enumAsInt(SomeClass::PublicScopedEnum value) { return static_cast<int>(value); }
+LIBSAMPLE_API inline int enumAsInt(SomeClass::PublicScopedEnum value)
+{ return static_cast<int>(value); }
class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough
{
@@ -109,29 +135,30 @@ public:
// only to cause namespace confusion
// enum SampleNamespace {
// };
- virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; }
+ virtual OkThisIsRecursiveEnough *someVirtualMethod(OkThisIsRecursiveEnough *arg) { return arg; }
inline OkThisIsRecursiveEnough *methodReturningTypeFromParentScope() { return nullptr; }
};
// The combination of the following two overloaded methods could trigger a
// problematic behaviour on the overload decisor, if it isn't working properly.
LIBSAMPLE_API void forceDecisorSideA(ObjectType *object = nullptr);
-LIBSAMPLE_API void forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object = 0);
+LIBSAMPLE_API void forceDecisorSideA(const Point &pt, const Str &text,
+ ObjectType *object = nullptr);
// The combination of the following two overloaded methods could trigger a
// problematic behaviour on the overload decisor, if it isn't working properly.
// This is a variation of forceDecisorSideB.
LIBSAMPLE_API void forceDecisorSideB(int a, ObjectType *object = nullptr);
-LIBSAMPLE_API void forceDecisorSideB(int a, const Point &pt, const Str &text, ObjectType *object = nullptr);
+LIBSAMPLE_API void forceDecisorSideB(int a, const Point &pt, const Str &text,
+ ObjectType *object = nullptr);
// Add a new signature on type system with only a Point value as parameter.
-LIBSAMPLE_API double passReferenceToValueType(const Point& point, double multiplier);
+LIBSAMPLE_API double passReferenceToValueType(const Point &point, double multiplier);
// Add a new signature on type system with only a ObjectType pointer as parameter.
-LIBSAMPLE_API int passReferenceToObjectType(const ObjectType& obj, int multiplier);
+LIBSAMPLE_API int passReferenceToObjectType(const ObjectType &obj, int multiplier);
extern LIBSAMPLE_API int variableInNamespace;
} // namespace SampleNamespace
#endif // SAMPLENAMESPACE_H
-
diff --git a/sources/shiboken6/tests/libsample/sbkdate.h b/sources/shiboken6/tests/libsample/sbkdate.h
index d102f62b8..5e1dd0b84 100644
--- a/sources/shiboken6/tests/libsample/sbkdate.h
+++ b/sources/shiboken6/tests/libsample/sbkdate.h
@@ -9,7 +9,7 @@
class LIBSAMPLE_API SbkDate
{
public:
- SbkDate(int d, int m, int y);
+ explicit SbkDate(int d, int m, int y);
int day() const;
int month() const;
@@ -22,4 +22,3 @@ private:
};
#endif // SBKDATE_H
-
diff --git a/sources/shiboken6/tests/libsample/simplefile.cpp b/sources/shiboken6/tests/libsample/simplefile.cpp
index e0e42e268..e51b14088 100644
--- a/sources/shiboken6/tests/libsample/simplefile.cpp
+++ b/sources/shiboken6/tests/libsample/simplefile.cpp
@@ -1,83 +1,73 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <stdlib.h>
-#include <string.h>
-#include <fstream>
#include "simplefile.h"
-class SimpleFile_p
+#include <cstdlib>
+#include <cstdio>
+#include <string>
+#include <filesystem>
+
+class SimpleFilePrivate
{
public:
- SimpleFile_p(const char* filename) : m_descriptor(nullptr), m_size(0)
- {
- m_filename = strdup(filename);
- }
+ LIBMINIMAL_DISABLE_COPY_MOVE(SimpleFilePrivate)
- ~SimpleFile_p()
- {
- free(m_filename);
- }
+ SimpleFilePrivate(const char *filename) : m_filename(filename) {}
+ ~SimpleFilePrivate() = default;
- char* m_filename;
- FILE* m_descriptor;
- long m_size;
+ std::string m_filename;
+ FILE *m_descriptor = nullptr;
+ long m_size = 0;
};
-SimpleFile::SimpleFile(const char* filename)
+SimpleFile::SimpleFile(const char *filename) :
+ p(std::make_unique<SimpleFilePrivate>(filename))
{
- p = new SimpleFile_p(filename);
}
SimpleFile::~SimpleFile()
{
close();
- delete p;
}
-const char* SimpleFile::filename()
+const char *SimpleFile::filename()
{
- return p->m_filename;
+ return p->m_filename.c_str();
}
-long SimpleFile::size()
+long SimpleFile::size() const
{
return p->m_size;
}
-bool
-SimpleFile::open()
+bool SimpleFile::open()
{
- if ((p->m_descriptor = fopen(p->m_filename, "rb")) == nullptr)
+ auto *descriptor = std::fopen(p->m_filename.c_str(), "rb");
+ if (descriptor == nullptr)
return false;
- fseek(p->m_descriptor, 0, SEEK_END);
- p->m_size = ftell(p->m_descriptor);
- rewind(p->m_descriptor);
+ p->m_descriptor = descriptor;
+ const auto size = std::filesystem::file_size(std::filesystem::path(p->m_filename));
+ p->m_size = long(size);
return true;
}
-void
-SimpleFile::close()
+void SimpleFile::close()
{
- if (p->m_descriptor) {
- fclose(p->m_descriptor);
+ if (p->m_descriptor != nullptr) {
+ std::fclose(p->m_descriptor);
p->m_descriptor = nullptr;
}
}
-bool
-SimpleFile::exists() const
+bool SimpleFile::exists() const
{
- std::ifstream ifile(p->m_filename);
- return !ifile.fail();
+ return std::filesystem::exists(std::filesystem::path(p->m_filename));
}
-bool
-SimpleFile::exists(const char* filename)
+bool SimpleFile::exists(const char *filename)
{
- std::ifstream ifile(filename);
- return !ifile.fail();
+ return std::filesystem::exists(std::filesystem::path(filename));
}
-
diff --git a/sources/shiboken6/tests/libsample/simplefile.h b/sources/shiboken6/tests/libsample/simplefile.h
index 765b46095..e4612c944 100644
--- a/sources/shiboken6/tests/libsample/simplefile.h
+++ b/sources/shiboken6/tests/libsample/simplefile.h
@@ -5,27 +5,30 @@
#define SIMPLEFILE_H
#include "libsamplemacros.h"
-#include <stdio.h>
-class SimpleFile_p;
+#include <memory>
+
+class SimpleFilePrivate;
class LIBSAMPLE_API SimpleFile
{
public:
- explicit SimpleFile(const char* filename);
+ LIBMINIMAL_DISABLE_COPY(SimpleFile)
+ LIBMINIMAL_DEFAULT_MOVE(SimpleFile)
+
+ explicit SimpleFile(const char *filename);
~SimpleFile();
- const char* filename();
- long size();
+ const char *filename();
+ long size() const;
bool open();
void close();
bool exists() const;
- static bool exists(const char* filename);
+ static bool exists(const char *filename);
private:
- SimpleFile_p *p;
+ std::unique_ptr<SimpleFilePrivate> p;
};
#endif // SIMPLEFILE_H
-
diff --git a/sources/shiboken6/tests/libsample/size.cpp b/sources/shiboken6/tests/libsample/size.cpp
index 5edb8a77b..0291d6e86 100644
--- a/sources/shiboken6/tests/libsample/size.cpp
+++ b/sources/shiboken6/tests/libsample/size.cpp
@@ -1,14 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <iostream>
#include "size.h"
-using namespace std;
+#include <iostream>
-void
-Size::show() const
+void Size::show() const
{
- cout << "(width: " << m_width << ", height: " << m_height << ")";
+ std::cout << "(width: " << m_width << ", height: " << m_height << ")";
}
-
diff --git a/sources/shiboken6/tests/libsample/size.h b/sources/shiboken6/tests/libsample/size.h
index ac57065af..2d194e96b 100644
--- a/sources/shiboken6/tests/libsample/size.h
+++ b/sources/shiboken6/tests/libsample/size.h
@@ -9,23 +9,26 @@
class LIBSAMPLE_API Size
{
public:
- Size(double width = 0.0, double height = 0.0) : m_width(width), m_height(height) {}
- ~Size() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Size)
- inline double width() { return m_width; }
+ explicit Size(double width = 0.0, double height = 0.0) noexcept :
+ m_width(width), m_height(height) {}
+ ~Size() = default;
+
+ inline double width() const { return m_width; }
inline void setWidth(double width) { m_width = width; }
- inline double height() { return m_height; }
+ inline double height() const { return m_height; }
inline void setHeight(double height) { m_height = height; }
inline double calculateArea() const { return m_width * m_height; }
// Comparison Operators
- inline bool operator<(const Size& other)
+ inline bool operator<(const Size &other)
{
return calculateArea() < other.calculateArea();
}
- inline bool operator>(const Size& other)
+ inline bool operator>(const Size &other)
{
// On some x86 hardware and compiler combinations, floating point
// comparisons may fail due to a hardware bug. One workaround is to
@@ -37,7 +40,7 @@ public:
return a > b;
}
- inline bool operator<=(const Size& other)
+ inline bool operator<=(const Size &other)
{
// See comments for operator>()
double a = calculateArea();
@@ -45,7 +48,7 @@ public:
return a <= b;
}
- inline bool operator>=(const Size& other)
+ inline bool operator>=(const Size &other)
{
return calculateArea() >= other.calculateArea();
}
@@ -56,28 +59,28 @@ public:
inline bool operator>=(double area) { return calculateArea() >= area; }
// Arithmetic Operators
- inline Size& operator+=(const Size& s)
+ inline Size &operator+=(const Size &s)
{
m_width += s.m_width;
m_height += s.m_height;
return *this;
}
- inline Size& operator-=(const Size& s)
+ inline Size &operator-=(const Size &s)
{
m_width -= s.m_width;
m_height -= s.m_height;
return *this;
}
- inline Size& operator*=(double mult)
+ inline Size &operator*=(double mult)
{
m_width *= mult;
m_height *= mult;
return *this;
}
- inline Size& operator/=(double div)
+ inline Size &operator/=(double div)
{
m_width /= div;
m_height /= div;
@@ -89,11 +92,11 @@ public:
// External operators
friend inline bool operator==(const Size&, const Size&);
friend inline bool operator!=(const Size&, const Size&);
- friend inline const Size operator+(const Size&, const Size&);
- friend inline const Size operator-(const Size&, const Size&);
- friend inline const Size operator*(const Size&, double);
- friend inline const Size operator*(double, const Size&);
- friend inline const Size operator/(const Size&, double);
+ friend inline Size operator+(const Size&, const Size&);
+ friend inline Size operator-(const Size&, const Size&);
+ friend inline Size operator*(const Size&, double);
+ friend inline Size operator*(double, const Size&);
+ friend inline Size operator/(const Size&, double);
friend inline bool operator<(double, const Size&);
friend inline bool operator>(double, const Size&);
@@ -108,70 +111,71 @@ private:
};
// Comparison Operators
-inline bool operator!=(const Size& s1, const Size& s2)
+inline bool operator!=(const Size &s1, const Size &s2)
{
return s1.m_width != s2.m_width || s1.m_height != s2.m_height;
}
-inline bool operator==(const Size& s1, const Size& s2)
+inline bool operator==(const Size &s1, const Size &s2)
{
return s1.m_width == s2.m_width && s1.m_height == s2.m_height;
}
-inline bool operator<(double area, const Size& s)
+inline bool operator<(double area, const Size &s)
{
return area < s.calculateArea();
}
-inline bool operator>(double area, const Size& s)
+inline bool operator>(double area, const Size &s)
{
return area > s.calculateArea();
}
-inline bool operator<=(double area, const Size& s)
+inline bool operator<=(double area, const Size &s)
{
return area <= s.calculateArea();
}
-inline bool operator>=(double area, const Size& s)
+inline bool operator>=(double area, const Size &s)
{
return area >= s.calculateArea();
}
// Arithmetic Operators
-inline const Size operator+(const Size& s1, const Size& s2)
+inline Size operator+(const Size &s1, const Size &s2)
{
return Size(s1.m_width + s2.m_width, s1.m_height + s2.m_height);
}
-inline const Size operator-(const Size& s1, const Size& s2)
+inline Size operator-(const Size &s1, const Size &s2)
{
return Size(s1.m_width - s2.m_width, s1.m_height - s2.m_height);
}
-inline const Size operator*(const Size& s, double mult)
+inline Size operator*(const Size &s, double mult)
{
return Size(s.m_width * mult, s.m_height * mult);
}
-inline const Size operator*(double mult, const Size& s)
+inline Size operator*(double mult, const Size &s)
{
return Size(s.m_width * mult, s.m_height * mult);
}
-inline const Size operator/(const Size& s, double div)
+inline Size operator/(const Size &s, double div)
{
return Size(s.m_width / div, s.m_height / div);
}
using real = double;
using ushort = unsigned short;
+
class LIBSAMPLE_API SizeF
{
public:
- SizeF(real width, real height) : m_width(width), m_height(height) {}
- real width() { return m_width; }
- real height() { return m_height; }
+ explicit SizeF(real width, real height) : m_width(width), m_height(height) {}
+ real width() const { return m_width; }
+ real height() const { return m_height; }
static inline ushort passTypedefOfUnsignedShort(ushort value) { return value; }
private:
real m_width;
@@ -179,4 +183,3 @@ private:
};
#endif // SIZE_H
-
diff --git a/sources/shiboken6/tests/libsample/sometime.cpp b/sources/shiboken6/tests/libsample/sometime.cpp
index 7f9bc24c3..ad9a0d81c 100644
--- a/sources/shiboken6/tests/libsample/sometime.cpp
+++ b/sources/shiboken6/tests/libsample/sometime.cpp
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "sometime.h"
-#include <stdio.h>
-void
-Time::setTime()
+#include <cstdio>
+
+void Time::setTime()
{
m_hour = 0;
m_minute = 0;
@@ -14,8 +14,7 @@ Time::setTime()
m_is_null = true;
}
-void
-Time::setTime(int h, int m, int s, int ms)
+void Time::setTime(int h, int m, int s, int ms)
{
m_hour = h;
m_minute = m;
@@ -24,15 +23,12 @@ Time::setTime(int h, int m, int s, int ms)
m_is_null = false;
}
-
-Time::NumArgs
-Time::somethingCompletelyDifferent()
+Time::NumArgs Time::somethingCompletelyDifferent()
{
return ZeroArgs;
}
-Time::NumArgs
-Time::somethingCompletelyDifferent(int h, int m, ImplicitConv ic, ObjectType* type)
+Time::NumArgs Time::somethingCompletelyDifferent(int, int, ImplicitConv ic, ObjectType *type)
{
if (type)
return FourArgs;
@@ -41,18 +37,17 @@ Time::somethingCompletelyDifferent(int h, int m, ImplicitConv ic, ObjectType* ty
return ThreeArgs;
}
-Str
-Time::toString() const
+Str Time::toString() const
{
if (m_is_null)
return Str();
char buffer[13];
- sprintf(buffer, "%02d:%02d:%02d.%03d", m_hour, m_minute, m_second, m_msec);
+ std::snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d.%03d",
+ m_hour, m_minute, m_second, m_msec);
return Str(buffer);
}
-bool
-Time::operator==(const Time& other) const
+bool Time::operator==(const Time &other) const
{
return m_hour == other.m_hour
&& m_minute == other.m_minute
@@ -61,8 +56,7 @@ Time::operator==(const Time& other) const
&& m_is_null == other.m_is_null;
}
-bool
-Time::operator!=(const Time& other) const
+bool Time::operator!=(const Time &other) const
{
return !operator==(other);
}
@@ -71,4 +65,3 @@ Time::operator Str() const
{
return Time::toString();
}
-
diff --git a/sources/shiboken6/tests/libsample/sometime.h b/sources/shiboken6/tests/libsample/sometime.h
index 0e3442db0..575d4b136 100644
--- a/sources/shiboken6/tests/libsample/sometime.h
+++ b/sources/shiboken6/tests/libsample/sometime.h
@@ -12,6 +12,8 @@
class LIBSAMPLE_API Time
{
public:
+ LIBMINIMAL_DEFAULT_COPY_MOVE(Time)
+
enum NumArgs {
ZeroArgs,
TwoArgs,
@@ -19,14 +21,12 @@ public:
FourArgs
};
- Time()
- : m_hour(0), m_minute(0), m_second(0), m_msec(0), m_is_null(true)
- {}
- Time(int h, int m, int s = 0, int ms = 0)
- : m_hour(h), m_minute(m), m_second(s), m_msec(ms), m_is_null(false)
+ Time() noexcept = default;
+ explicit Time(int h, int m, int s = 0, int ms = 0) noexcept:
+ m_hour(h), m_minute(m), m_second(s), m_msec(ms), m_is_null(false)
{}
- ~Time() {}
+ ~Time() = default;
inline bool isNull() const { return m_is_null; }
@@ -48,20 +48,19 @@ public:
ObjectType *type = nullptr);
Str toString() const;
- bool operator==(const Time& other) const;
- bool operator!=(const Time& other) const;
+ bool operator==(const Time &other) const;
+ bool operator!=(const Time &other) const;
// This cast operator must become an implicit conversion of Str.
operator Str() const;
private:
- int m_hour;
- int m_minute;
- int m_second;
- int m_msec;
+ int m_hour = 0;
+ int m_minute = 0;
+ int m_second = 0;
+ int m_msec = 0;
- bool m_is_null;
+ bool m_is_null = true;
};
#endif // SOMETIME_H
-
diff --git a/sources/shiboken6/tests/libsample/stdcomplex.cpp b/sources/shiboken6/tests/libsample/stdcomplex.cpp
new file mode 100644
index 000000000..847174387
--- /dev/null
+++ b/sources/shiboken6/tests/libsample/stdcomplex.cpp
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "stdcomplex.h"
+
+#include <iostream>
+
+StdComplex::StdComplex() noexcept = default;
+
+StdComplex::StdComplex(double re, double img) noexcept : m_impl(re, img)
+{
+}
+
+StdComplex::operator int() const
+{
+ return std::lround(abs_value());
+}
+
+StdComplex::StdComplex(const Impl &impl) noexcept : m_impl(impl)
+{
+}
+
+StdComplex StdComplex::pow(const StdComplex &exp) const
+{
+ return StdComplex(std::pow(m_impl, exp.m_impl));
+}
+
+std::ostream &operator<<(std::ostream &str, const StdComplex &c)
+{
+ str << "Complex(" << c.real() << ", " << c.imag() << ')';
+ return str;
+}
diff --git a/sources/shiboken6/tests/libsample/stdcomplex.h b/sources/shiboken6/tests/libsample/stdcomplex.h
new file mode 100644
index 000000000..b39b80612
--- /dev/null
+++ b/sources/shiboken6/tests/libsample/stdcomplex.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef STDCOMPLEX_H
+#define STDCOMPLEX_H
+
+#include "libsamplemacros.h"
+
+#include <complex>
+#include <iosfwd>
+
+// A complex number based on std::complex for exercising esoteric number
+// protocols (Py_nb_). For standard number protocols, see Point.
+
+class LIBSAMPLE_API StdComplex
+{
+ using Impl = std::complex<double>;
+
+public:
+ StdComplex() noexcept;
+ explicit StdComplex(double re, double img) noexcept;
+
+ double real() const { return m_impl.real(); }
+ double imag() const { return m_impl.imag(); }
+
+ double abs_value() const { return std::abs(m_impl); } // abs() is reserved Python word
+
+ StdComplex pow(const StdComplex &exp) const;
+
+ operator double() const { return abs_value(); }
+ operator int() const;
+
+ friend inline bool operator==(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return c1.m_impl == c2.m_impl; }
+ friend inline bool operator!=(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return c1.m_impl != c2.m_impl; }
+
+ friend inline StdComplex operator+(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return StdComplex(c1.m_impl + c2.m_impl); }
+ friend inline StdComplex operator-(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return StdComplex(c1.m_impl - c2.m_impl); }
+ friend inline StdComplex operator*(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return StdComplex(c1.m_impl * c2.m_impl); }
+ friend inline StdComplex operator/(const StdComplex &c1, const StdComplex &c2) noexcept
+ { return StdComplex(c1.m_impl / c2.m_impl); }
+
+private:
+ explicit StdComplex(const Impl &impl) noexcept;
+
+ Impl m_impl;
+};
+
+std::ostream &operator<<(std::ostream &str, const StdComplex &c);
+
+#endif // STDCOMPLEX_H
diff --git a/sources/shiboken6/tests/libsample/str.cpp b/sources/shiboken6/tests/libsample/str.cpp
index f8d1b726f..742c0bb01 100644
--- a/sources/shiboken6/tests/libsample/str.cpp
+++ b/sources/shiboken6/tests/libsample/str.cpp
@@ -2,91 +2,73 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "str.h"
+
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
-using namespace std;
-
-Str::Str(const Str& s)
-{
- init(s.cstring());
-}
-
Str::Str(char c)
{
char str[2] = { c, 0 };
init(str);
}
-Str::Str(const char* cstr)
+Str::Str(const char *cstr)
{
init(cstr);
}
-void
-Str::init(const char* cstr)
+void Str::init(const char *cstr)
{
if (cstr)
m_str = cstr;
}
-Str::~Str()
-{
-}
-
-Str
-Str::arg(const Str& s) const
+Str Str::arg(const Str &s) const
{
size_t idx = m_str.find_first_of("%VAR");
- if (idx == std::string::npos) {
+ if (idx == std::string::npos)
return *this;
- } else {
- std::string result = m_str;
- result.replace(idx, 4, s.m_str);
- return result.c_str();
- }
+
+ std::string result = m_str;
+ result.replace(idx, 4, s.m_str);
+ return result.c_str();
}
-Str&
-Str::append(const Str& s)
+Str &Str::append(const Str &s)
{
m_str += s.m_str;
return *this;
}
-Str&
-Str::prepend(const Str& s)
+Str &Str::prepend(const Str &s)
{
m_str = s.m_str + m_str;
return *this;
}
-const char*
-Str::cstring() const
+const char *Str::cstring() const
{
return m_str.c_str();
}
-int
-Str::toInt(bool* ok, int base) const
+int Str::toInt(bool *ok, int base) const
{
- bool my_ok;
int result = 0;
- istringstream conv(m_str);
+ std::istringstream conv(m_str);
switch (base) {
- case 8:
- conv >> std::oct >> result;
- break;
- case 10:
- conv >> std::dec >> result;
- break;
- case 16:
- conv >> std::hex >> result;
- break;
+ case 8:
+ conv >> std::oct >> result;
+ break;
+ case 10:
+ conv >> std::dec >> result;
+ break;
+ case 16:
+ conv >> std::hex >> result;
+ break;
}
- my_ok = istringstream::eofbit & conv.rdstate();
+ const bool my_ok = std::istringstream::eofbit & conv.rdstate();
if (!my_ok)
result = 0;
if (ok)
@@ -94,20 +76,17 @@ Str::toInt(bool* ok, int base) const
return result;
}
-void
-Str::show() const
+void Str::show() const
{
- printf("%s", cstring());
+ std::printf("%s", cstring());
}
-char
-Str::get_char(int pos) const
+char Str::get_char(int pos) const
{
return m_str[pos];
}
-bool
-Str::set_char(int pos, char ch)
+bool Str::set_char(int pos, char ch)
{
m_str[pos] = ch;
return true;
@@ -115,42 +94,42 @@ Str::set_char(int pos, char ch)
Str Str::operator+(int number) const
{
- ostringstream in;
+ std::ostringstream in;
in << m_str << number;
return in.str().c_str();
}
-bool Str::operator==(const Str& other) const
+bool Str::operator==(const Str &other) const
{
return m_str == other.m_str;
}
-Str operator+(int number, const Str& str)
+Str operator+(int number, const Str &str)
{
- ostringstream in;
+ std::ostringstream in;
in << number << str.m_str;
return in.str().c_str();
}
-bool Str::operator<(const Str& other) const
+bool Str::operator<(const Str &other) const
{
return m_str < other.m_str;
}
-unsigned int strHash(const Str& str)
+unsigned int strHash(const Str &str)
{
unsigned int result = 0;
for (char c : str.m_str)
- result = 5u * result + unsigned(c);
+ result = 5U * result + unsigned(c);
return result;
}
-void changePStr(PStr* pstr, const char* suffix)
+void changePStr(PStr *pstr, const char *suffix)
{
pstr->append(suffix);
}
-void duplicatePStr(PStr* pstr)
+void duplicatePStr(PStr *pstr)
{
if (!pstr)
return;
diff --git a/sources/shiboken6/tests/libsample/str.h b/sources/shiboken6/tests/libsample/str.h
index 0b75348c7..6b3386cef 100644
--- a/sources/shiboken6/tests/libsample/str.h
+++ b/sources/shiboken6/tests/libsample/str.h
@@ -3,24 +3,23 @@
#ifndef STR_H
#define STR_H
-#include <string>
#include "libsamplemacros.h"
+#include <string>
+
class LIBSAMPLE_API Str
{
public:
- Str(const Str& s);
Str(char c);
- Str(const char* cstr = "");
- ~Str();
+ Str(const char *cstr = "");
- Str arg(const Str& s) const;
+ Str arg(const Str &s) const;
- Str& append(const Str& s);
- Str& prepend(const Str& s);
+ Str &append(const Str &s);
+ Str &prepend(const Str &s);
- const char* cstring() const;
+ const char *cstring() const;
char get_char(int pos) const;
bool set_char(int pos, char ch);
@@ -28,26 +27,26 @@ public:
void show() const;
- inline int size() const { return m_str.size(); }
+ inline int size() const { return int(m_str.size()); }
// nonsense operator just to test reverse operators
Str operator+(int number) const;
- bool operator==(const Str& other) const;
- bool operator<(const Str& other) const;
+ bool operator==(const Str &other) const;
+ bool operator<(const Str &other) const;
private:
- void init(const char* cstr);
+ void init(const char *cstr);
std::string m_str;
- friend LIBSAMPLE_API Str operator+(int number, const Str& str);
- friend LIBSAMPLE_API unsigned int strHash(const Str& str);
+ friend LIBSAMPLE_API Str operator+(int number, const Str &str);
+ friend LIBSAMPLE_API unsigned int strHash(const Str &str);
};
-LIBSAMPLE_API Str operator+(int number, const Str& str);
-LIBSAMPLE_API unsigned int strHash(const Str& str);
+LIBSAMPLE_API Str operator+(int number, const Str &str);
+LIBSAMPLE_API unsigned int strHash(const Str &str);
using PStr = Str;
-LIBSAMPLE_API void changePStr(PStr* pstr, const char* suffix);
+LIBSAMPLE_API void changePStr(PStr *pstr, const char *suffix);
LIBSAMPLE_API void duplicatePStr(PStr *pstr = nullptr);
#endif // STR_H
diff --git a/sources/shiboken6/tests/libsample/strlist.cpp b/sources/shiboken6/tests/libsample/strlist.cpp
index 845b83a0d..5840a0516 100644
--- a/sources/shiboken6/tests/libsample/strlist.cpp
+++ b/sources/shiboken6/tests/libsample/strlist.cpp
@@ -5,15 +5,13 @@
#include <algorithm>
-bool
-StrList::operator==(const std::list<Str>& other) const
+bool StrList::operator==(const std::list<Str> &other) const
{
return size() == other.size()
&& std::equal(begin(), end(), other.begin());
}
-Str
-StrList::join(const Str& sep) const
+Str StrList::join(const Str &sep) const
{
Str result;
const auto i1 = begin();
diff --git a/sources/shiboken6/tests/libsample/strlist.h b/sources/shiboken6/tests/libsample/strlist.h
index 52b7e5951..01865a5b4 100644
--- a/sources/shiboken6/tests/libsample/strlist.h
+++ b/sources/shiboken6/tests/libsample/strlist.h
@@ -4,10 +4,10 @@
#ifndef STRLIST_H
#define STRLIST_H
-#include <list>
+#include "libsamplemacros.h"
#include "str.h"
-#include "libsamplemacros.h"
+#include <list>
class LIBSAMPLE_API StrList : public std::list<Str>
{
@@ -19,20 +19,29 @@ public:
ListOfStrCtor
};
- inline StrList() : m_ctorUsed(NoParamsCtor) {}
- inline explicit StrList(const Str& str) : m_ctorUsed(StrCtor) { push_back(str); }
- inline StrList(const StrList& lst) : std::list<Str>(lst), m_ctorUsed(CopyCtor) {}
- inline StrList(const std::list<Str>& lst) : std::list<Str>(lst), m_ctorUsed(ListOfStrCtor) {}
+ inline StrList() = default;
+ inline StrList(const std::list<Str> &lst) :
+ std::list<Str>(lst), m_ctorUsed(ListOfStrCtor) {}
+ inline explicit StrList(const Str &str) :
+ m_ctorUsed(StrCtor) { push_back(str); }
+ inline StrList(const StrList &lst) :
+ std::list<Str>(lst), m_ctorUsed(CopyCtor) {}
+
+ StrList(StrList &&) = default;
+ StrList &operator=(const StrList &) = default;
+ StrList &operator=(StrList &&) = default;
+ ~StrList() = default;
+
+ inline void append(const Str &str) { push_back(str); }
+ Str join(const Str &sep) const;
- inline void append(Str str) { push_back(str); }
- Str join(const Str& sep) const;
+ bool operator==(const std::list<Str> &other) const;
+ inline bool operator!=(const std::list<Str> &other) const { return !(*this == other); }
- bool operator==(const std::list<Str>& other) const;
- inline bool operator!=(const std::list<Str>& other) const { return !(*this == other); }
+ CtorEnum constructorUsed() const { return m_ctorUsed; }
- CtorEnum constructorUsed() { return m_ctorUsed; }
private:
- CtorEnum m_ctorUsed;
+ CtorEnum m_ctorUsed = NoParamsCtor;
};
using PStrList = StrList;
diff --git a/sources/shiboken6/tests/libsample/templateptr.cpp b/sources/shiboken6/tests/libsample/templateptr.cpp
index 44be79cfc..a73f78417 100644
--- a/sources/shiboken6/tests/libsample/templateptr.cpp
+++ b/sources/shiboken6/tests/libsample/templateptr.cpp
@@ -3,6 +3,6 @@
#include "templateptr.h"
-void TemplatePtr::dummy(std::list<std::pair<BlackBox *, BlackBox *> > & items)
+void TemplatePtr::dummy(std::list<std::pair<BlackBox *, BlackBox *> > &)
{
}
diff --git a/sources/shiboken6/tests/libsample/templateptr.h b/sources/shiboken6/tests/libsample/templateptr.h
index e8145b90d..bf230c363 100644
--- a/sources/shiboken6/tests/libsample/templateptr.h
+++ b/sources/shiboken6/tests/libsample/templateptr.h
@@ -4,15 +4,16 @@
#ifndef TEMPLATEPTR_H
#define TEMPLATEPTR_H
-#include <utility>
-#include <list>
#include "libsamplemacros.h"
#include "blackbox.h"
+#include <utility>
+#include <list>
+
class LIBSAMPLE_API TemplatePtr
{
public:
- void dummy(std::list<std::pair<BlackBox *, BlackBox *> > & items);
+ void dummy(std::list<std::pair<BlackBox *, BlackBox *> > &items);
};
-#endif
+#endif // TEMPLATEPTR_H
diff --git a/sources/shiboken6/tests/libsample/transform.cpp b/sources/shiboken6/tests/libsample/transform.cpp
index d23cb6179..5ccf5d1ed 100644
--- a/sources/shiboken6/tests/libsample/transform.cpp
+++ b/sources/shiboken6/tests/libsample/transform.cpp
@@ -4,37 +4,25 @@
#include "transform.h"
-#ifdef _WIN32
-#include <math.h>
-#include <float.h>
-static inline bool isfinite(double a) { return _finite(a); }
-#else
#include <cmath>
-#endif
-using namespace std;
-
-Point applyHomogeneousTransform(
- const Point& in,
- double m11, double m12, double m13,
- double m21, double m22, double m23,
- double m31, double m32, double m33,
- bool* okay)
+Point applyHomogeneousTransform(const Point &in,
+ double m11, double m12, double m13,
+ double m21, double m22, double m23,
+ double m31, double m32, double m33,
+ bool *okay)
{
double x = m11 * in.x() + m12 * in.y() + m13;
double y = m21 * in.x() + m22 * in.y() + m23;
double w = m31 * in.x() + m32 * in.y() + m33;
- if (isfinite(w) && fabs(w) > 1e-10)
- {
+ if (std::isfinite(w) && fabs(w) > 1e-10) {
if (okay)
*okay = true;
- return Point(x / w, y / w);
- }
- else
- {
- if (okay)
- *okay = false;
- return Point();
+ return {x / w, y / w};
}
+
+ if (okay)
+ *okay = false;
+ return {};
}
diff --git a/sources/shiboken6/tests/libsample/transform.h b/sources/shiboken6/tests/libsample/transform.h
index a39445c40..34ebf40d3 100644
--- a/sources/shiboken6/tests/libsample/transform.h
+++ b/sources/shiboken6/tests/libsample/transform.h
@@ -9,12 +9,10 @@
#include "libsamplemacros.h"
-LIBSAMPLE_API Point
-applyHomogeneousTransform(
- const Point& in,
- double m11, double m12, double m13,
- double m21, double m22, double m23,
- double m31, double m32, double m33,
- bool* okay);
+LIBSAMPLE_API Point applyHomogeneousTransform(const Point &in,
+ double m11, double m12, double m13,
+ double m21, double m22, double m23,
+ double m31, double m32, double m33,
+ bool *okay);
#endif // TRANSFORM_H
diff --git a/sources/shiboken6/tests/libsample/valueandvirtual.h b/sources/shiboken6/tests/libsample/valueandvirtual.h
index d5a9be6b5..799e11e40 100644
--- a/sources/shiboken6/tests/libsample/valueandvirtual.h
+++ b/sources/shiboken6/tests/libsample/valueandvirtual.h
@@ -4,19 +4,22 @@
#ifndef VALUEANDVIRTUAL_H
#define VALUEANDVIRTUAL_H
+#include "libsamplemacros.h"
+
class ValueAndVirtual
{
public:
- ValueAndVirtual(int id) : m_id(id) {}
- ValueAndVirtual(const ValueAndVirtual &other) { m_id = other.m_id; }
+ LIBMINIMAL_DEFAULT_COPY_MOVE(ValueAndVirtual)
+
+ explicit ValueAndVirtual(int id) noexcept : m_id(id) {}
+ virtual ~ValueAndVirtual() = default;
bool operator()(int id, int id2) { return id == id2; }
- inline int id() { return m_id; }
- virtual ~ValueAndVirtual() {};
+ inline int id() const { return m_id; }
+
private:
int m_id;
};
#endif // VALUEANDVIRTUAL_H
-
diff --git a/sources/shiboken6/tests/libsample/virtualmethods.cpp b/sources/shiboken6/tests/libsample/virtualmethods.cpp
index 6c7b4a004..515564664 100644
--- a/sources/shiboken6/tests/libsample/virtualmethods.cpp
+++ b/sources/shiboken6/tests/libsample/virtualmethods.cpp
@@ -5,14 +5,12 @@
int VirtualDtor::dtor_called = 0;
-double
-VirtualMethods::virtualMethod0(Point pt, int val, Complex cpx, bool b)
+double VirtualMethods::virtualMethod0(Point pt, int val, Complex cpx, bool b)
{
return (pt.x() * pt.y() * val) + cpx.imag() + ((int) b);
}
-bool
-VirtualMethods::createStr(const char* text, Str*& ret)
+bool VirtualMethods::createStr(const char *text, Str *&ret)
{
if (!text) {
ret = nullptr;
@@ -23,8 +21,7 @@ VirtualMethods::createStr(const char* text, Str*& ret)
return true;
}
-void
-VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const
+void VirtualMethods::getMargins(int *left, int *top, int *right, int *bottom) const
{
*left = m_left;
*top = m_top;
@@ -32,6 +29,11 @@ VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const
*bottom = m_bottom;
}
+int VirtualMethods::recursionOnModifiedVirtual(Str) const
+{
+ return 0;
+}
+
const Str & VirtualMethods::returnConstRef() const
{
static const Str result;
diff --git a/sources/shiboken6/tests/libsample/virtualmethods.h b/sources/shiboken6/tests/libsample/virtualmethods.h
index c6ff560fc..b7172ad0d 100644
--- a/sources/shiboken6/tests/libsample/virtualmethods.h
+++ b/sources/shiboken6/tests/libsample/virtualmethods.h
@@ -17,11 +17,10 @@
class LIBSAMPLE_API VirtualMethods
{
public:
- VirtualMethods(Str name = "VirtualMethods") : m_name(name)
- {
- m_left = m_top = m_right = m_bottom = 0;
- }
- virtual ~VirtualMethods() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(VirtualMethods)
+
+ explicit VirtualMethods(Str name = "VirtualMethods") : m_name(name) {}
+ virtual ~VirtualMethods() = default;
virtual double virtualMethod0(Point pt, int val, Complex cpx, bool b);
double callVirtualMethod0(Point pt, int val, Complex cpx, bool b)
@@ -61,12 +60,14 @@ public:
void callCallMe() { callMe(); }
// Passing reference to pointers.
- virtual bool createStr(const char* text, Str*& ret);
- bool callCreateStr(const char* text, Str*& ret) { return createStr(text, ret); }
+ virtual bool createStr(const char *text, Str *&ret);
+ bool callCreateStr(const char *text, Str *&ret) { return createStr(text, ret); }
// Return a non-binded method
- std::list<Str> callStrListToStdList(const StrList& strList) { return strListToStdList(strList); }
- virtual std::list<Str> strListToStdList(const StrList& strList ) { return strList; }
+ std::list<Str> callStrListToStdList(const StrList &strList)
+ { return strListToStdList(strList); }
+ virtual std::list<Str> strListToStdList(const StrList &strList )
+ { return strList; }
void setMargins(int left, int top, int right, int bottom)
{
@@ -75,16 +76,16 @@ public:
m_right = right;
m_bottom = bottom;
}
- virtual void getMargins(int* left, int* top, int* right, int* bottom) const;
- void callGetMargins(int* left, int* top, int* right, int* bottom) const
+ virtual void getMargins(int *left, int *top, int *right, int *bottom) const;
+ void callGetMargins(int *left, int *top, int *right, int *bottom) const
{
getMargins(left, top, right, bottom);
}
- virtual int recursionOnModifiedVirtual(Str arg) const { return 0; }
+ virtual int recursionOnModifiedVirtual(Str arg) const;
int callRecursionOnModifiedVirtual(Str arg) const { return recursionOnModifiedVirtual(arg); }
- virtual const Str & returnConstRef() const;
+ virtual const Str &returnConstRef() const;
virtual int stringViewLength(std::string_view in) const;
@@ -94,10 +95,10 @@ protected:
private:
Str m_name;
- int m_left;
- int m_top;
- int m_right;
- int m_bottom;
+ int m_left = 0;
+ int m_top = 0;
+ int m_right = 0;
+ int m_bottom = 0;
};
class LIBSAMPLE_API VirtualDaughter : public VirtualMethods
@@ -128,10 +129,12 @@ public:
class LIBSAMPLE_API VirtualDtor
{
public:
- VirtualDtor() {}
+ LIBMINIMAL_DEFAULT_COPY_MOVE(VirtualDtor)
+
+ VirtualDtor() noexcept = default;
virtual ~VirtualDtor() { dtor_called++; }
- static VirtualDtor* create() { return new VirtualDtor(); }
+ static VirtualDtor *create() { return new VirtualDtor(); }
static int dtorCalled() { return dtor_called; }
static void resetDtorCounter() { dtor_called = 0; }
@@ -140,4 +143,3 @@ private:
};
#endif // VIRTUALMETHODS_H
-
diff --git a/sources/shiboken6/tests/libsample/voidholder.h b/sources/shiboken6/tests/libsample/voidholder.h
index b5e59ba3d..3f0f4d973 100644
--- a/sources/shiboken6/tests/libsample/voidholder.h
+++ b/sources/shiboken6/tests/libsample/voidholder.h
@@ -9,21 +9,24 @@
class VoidHolder
{
public:
- explicit VoidHolder(void *ptr = nullptr) : m_ptr(ptr) {}
- ~VoidHolder() {}
- inline void* voidPointer() { return m_ptr; }
- inline static void* gimmeMeSomeVoidPointer()
+ LIBMINIMAL_DEFAULT_COPY_MOVE(VoidHolder)
+
+ explicit VoidHolder(void *ptr = nullptr) noexcept : m_ptr(ptr) {}
+ ~VoidHolder() = default;
+
+ inline void *voidPointer() { return m_ptr; }
+ inline static void *gimmeMeSomeVoidPointer()
{
- static void* pointerToSomething = new VoidHolder();
+ static void *pointerToSomething = new VoidHolder();
return pointerToSomething;
}
void *takeVoidPointer(void *item)
{
return item;
}
+
private:
- void* m_ptr;
+ void *m_ptr;
};
#endif // VOIDHOLDER_H
-
diff --git a/sources/shiboken6/tests/libsmart/CMakeLists.txt b/sources/shiboken6/tests/libsmart/CMakeLists.txt
index 1a3a989da..95f0cffd6 100644
--- a/sources/shiboken6/tests/libsmart/CMakeLists.txt
+++ b/sources/shiboken6/tests/libsmart/CMakeLists.txt
@@ -1,10 +1,19 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(libsmart)
set(libsmart_SRC
-smart.cpp
-stdsharedptrtestbench.cpp
-stdoptionaltestbench.cpp
-stduniqueptrtestbench.cpp
+libsmartmacros.h
+smart.cpp smart.h
+smart_integer.h
+smart_obj.h
+smart_registry.h
+smart_sharedptr.h
+smart_test.h
+stdoptionaltestbench.cpp stdoptionaltestbench.h
+stdsharedptrtestbench.cpp stdsharedptrtestbench.h
+stduniqueptrtestbench.cpp stduniqueptrtestbench.h
)
add_library(libsmart SHARED ${libsmart_SRC})
diff --git a/sources/shiboken6/tests/libsmart/smart.cpp b/sources/shiboken6/tests/libsmart/smart.cpp
index 58f84474b..2273040f9 100644
--- a/sources/shiboken6/tests/libsmart/smart.cpp
+++ b/sources/shiboken6/tests/libsmart/smart.cpp
@@ -268,7 +268,5 @@ Smart::Integer2::Integer2()
{
}
-Smart::Integer2::Integer2(const Smart::Integer2 &other)
- : Integer (other)
-{
-}
+Smart::Integer2::Integer2(const Smart::Integer2 &) = default;
+Smart::Integer2 &Smart::Integer2::operator=(const Integer2 &) = default;
diff --git a/sources/shiboken6/tests/libsmart/smart.h b/sources/shiboken6/tests/libsmart/smart.h
index 9819ef43d..1f610b302 100644
--- a/sources/shiboken6/tests/libsmart/smart.h
+++ b/sources/shiboken6/tests/libsmart/smart.h
@@ -8,6 +8,7 @@
#include "smart_integer.h"
#include "smart_obj.h"
#include "smart_registry.h"
+#include "smart_test.h"
#include "stdsharedptrtestbench.h"
#include "stdoptionaltestbench.h"
#include "stduniqueptrtestbench.h"
diff --git a/sources/shiboken6/tests/libsmart/smart_integer.h b/sources/shiboken6/tests/libsmart/smart_integer.h
index 5135ec9e4..42a441a00 100644
--- a/sources/shiboken6/tests/libsmart/smart_integer.h
+++ b/sources/shiboken6/tests/libsmart/smart_integer.h
@@ -11,6 +11,8 @@ public:
Integer();
Integer(const Integer &other);
Integer &operator=(const Integer &other);
+ Integer(Integer &&other) noexcept = default;
+ Integer &operator=(Integer &&other) noexcept = default;
~Integer();
void printInteger() const;
@@ -56,7 +58,11 @@ namespace Smart {
class LIB_SMART_API Integer2 : public Integer {
public:
Integer2();
- Integer2(const Integer2 &other);
+ Integer2(const Integer2 &);
+ Integer2 &operator=(const Integer2 &);
+ Integer2(Integer2 &&other) = delete;
+ Integer2 &operator=(Integer2 &&other) = delete;
+ ~Integer2() = default;
};
} // namespace Smart
diff --git a/sources/shiboken6/tests/libsmart/smart_obj.h b/sources/shiboken6/tests/libsmart/smart_obj.h
index 901d69696..9f4f8425d 100644
--- a/sources/shiboken6/tests/libsmart/smart_obj.h
+++ b/sources/shiboken6/tests/libsmart/smart_obj.h
@@ -17,6 +17,10 @@ namespace Smart { class Integer2; }
class LIB_SMART_API Obj {
public:
Obj();
+ Obj(const Obj &other) = delete;
+ Obj &operator=(const Obj &other) = delete;
+ Obj(Obj &&other) = delete;
+ Obj &operator=(Obj &&other) = delete;
virtual ~Obj();
void printObj();
diff --git a/sources/shiboken6/tests/libsmart/smart_sharedptr.h b/sources/shiboken6/tests/libsmart/smart_sharedptr.h
index 7d0365dd0..dc665810a 100644
--- a/sources/shiboken6/tests/libsmart/smart_sharedptr.h
+++ b/sources/shiboken6/tests/libsmart/smart_sharedptr.h
@@ -20,6 +20,8 @@ struct SharedPtrBase
template <class T>
class SharedPtr : public SharedPtrBase {
public:
+ LIBMINIMAL_DEFAULT_MOVE(SharedPtr)
+
SharedPtr() { logDefaultConstructor(typeid(T).name(), this); }
SharedPtr(T *v) : mPtr(v)
@@ -38,9 +40,10 @@ public:
logCopyConstructor(typeid(T).name(), this, data());
}
- SharedPtr& operator=(const SharedPtr& other)
+ SharedPtr &operator=(const SharedPtr &other)
{
- mPtr = other.mPtr;
+ if (this != &other)
+ mPtr = other.mPtr;
return *this;
}
diff --git a/sources/shiboken6/tests/libsmart/smart_test.h b/sources/shiboken6/tests/libsmart/smart_test.h
new file mode 100644
index 000000000..89d8cbc7c
--- /dev/null
+++ b/sources/shiboken6/tests/libsmart/smart_test.h
@@ -0,0 +1,13 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef SMART_TEST_H
+#define SMART_TEST_H
+
+namespace Test {
+
+enum DummyEnum { Dummy1, Dummy2 };
+
+}
+
+#endif // SMART_TEST_H
diff --git a/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.cpp b/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.cpp
index e1056412c..df4b566fa 100644
--- a/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.cpp
+++ b/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.cpp
@@ -17,6 +17,17 @@ std::ostream &operator<<(std::ostream &str, const std::unique_ptr<Integer> &p)
return str;
}
+std::ostream &operator<<(std::ostream &str, const std::unique_ptr<Smart::Integer2> &p)
+{
+ str << "unique_ptr<Integer>(";
+ if (p.get())
+ str << p->value();
+ else
+ str << "nullptr";
+ str << ')';
+ return str;
+}
+
std::ostream &operator<<(std::ostream &str, const std::unique_ptr<int> &p)
{
str << "unique_ptr<int>(";
@@ -115,3 +126,8 @@ int StdUniquePtrVirtualMethodTester::doModifyIntegerByValue(std::unique_ptr<Inte
{
return p->value() + 1;
}
+
+void StdUniquePtrTestBench::printInteger2(const std::unique_ptr<Smart::Integer2> &p)
+{
+ std::cerr << __FUNCTION__ << ' ' << p << '\n';
+}
diff --git a/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.h b/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.h
index 8d3db740a..868c6d08c 100644
--- a/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.h
+++ b/sources/shiboken6/tests/libsmart/stduniqueptrtestbench.h
@@ -9,6 +9,9 @@
#include <memory>
class Integer;
+namespace Smart {
+class Integer2;
+}
class LIB_SMART_API StdUniquePtrTestBench
{
@@ -18,6 +21,7 @@ public:
static std::unique_ptr<Integer> createInteger(int v = 42);
static std::unique_ptr<Integer> createNullInteger();
+ static void printInteger2(const std::unique_ptr<Smart::Integer2> &p);
static void printInteger(const std::unique_ptr<Integer> &p);
static void takeInteger(std::unique_ptr<Integer> p); // Call with std::move()
diff --git a/sources/shiboken6/tests/minimalbinding/CMakeLists.txt b/sources/shiboken6/tests/minimalbinding/CMakeLists.txt
index 1b6b37e31..7f132bd34 100644
--- a/sources/shiboken6/tests/minimalbinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/minimalbinding/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(minimal)
set(minimal_TYPESYSTEM
@@ -6,22 +9,30 @@ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_minimal.xml
set(minimal_SRC
${CMAKE_CURRENT_BINARY_DIR}/minimal/minimal_module_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/minimal/containeruser_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/minimal/obj_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/minimal/val_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/minimal/listuser_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/minimal/spanuser_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/minimal/minbooluser_wrapper.cpp
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/minimal-binding.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt" @ONLY)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
add_custom_command(
-OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
-BYPRODUCTS ${minimal_SRC}
-COMMAND Shiboken6::shiboken6 --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt ${GENERATOR_EXTRA_FLAGS}
-DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
-WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-COMMENT "Running generator for 'minimal' test binding..."
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${minimal_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt
+ ${GENERATOR_EXTRA_FLAGS}
+ DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for 'minimal' test binding..."
)
add_library(minimal MODULE ${minimal_SRC})
diff --git a/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py
index 2b3f8638b..946a869db 100644
--- a/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py
+++ b/sources/shiboken6/tests/minimalbinding/brace_pattern_test.py
@@ -11,8 +11,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from shiboken6 import Shiboken
-_init_pyside_extension() # trigger bootstrap
+from shiboken6 import Shiboken # noqa: F401
from shibokensupport.signature.lib.tool import build_brace_pattern
@@ -22,8 +21,9 @@ against a slower reference implementation.
The pattern is crucial, because it is used heavily in signature.parser .
"""
-# A slow reference parser for braces and strings
+
def check(s):
+ """A slow reference parser for braces and strings"""
open, close = "[{(<", "]})>"
escape, quote = "\\", '"'
instring = blind = False
@@ -42,8 +42,7 @@ def check(s):
stack.append(c)
elif c in close:
pos = close.index(c)
- if ((len(stack) > 0) and
- (open[pos] == stack[len(stack)-1])):
+ if len(stack) > 0 and open[pos] == stack[len(stack) - 1]:
stack.pop()
else:
return False
diff --git a/sources/shiboken6/tests/minimalbinding/containeruser_test.py b/sources/shiboken6/tests/minimalbinding/containeruser_test.py
new file mode 100644
index 000000000..25d683957
--- /dev/null
+++ b/sources/shiboken6/tests/minimalbinding/containeruser_test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from shiboken_paths import init_paths
+init_paths()
+
+from minimal import ContainerUser
+
+
+class ContainerTest(unittest.TestCase):
+ """Simple test for converting std::vector and using an opaque container.
+ For advanced tests, see ListUser."""
+ def testVectorConversion(self):
+ v = ContainerUser.createIntVector(4)
+ self.assertEqual(ContainerUser.sumIntVector(v), 6)
+
+ def testVectorOpaqueContainer(self):
+ cu = ContainerUser()
+ oc = cu.intVector()
+ self.assertEqual(oc[0], 1)
+ oc[0] = 42
+ self.assertEqual(cu.intVector()[0], 42)
+
+ def testArrayConversion(self):
+ v = ContainerUser.createIntArray()
+ self.assertEqual(ContainerUser.sumIntArray(v), 6)
+
+ def testArrayOpaqueContainer(self):
+ cu = ContainerUser()
+ oc = cu.intArray()
+ self.assertEqual(oc[0], 1)
+ oc[0] = 42
+ self.assertEqual(cu.intArray()[0], 42)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken6/tests/minimalbinding/global.h b/sources/shiboken6/tests/minimalbinding/global.h
index 573e826d7..fc5c59a26 100644
--- a/sources/shiboken6/tests/minimalbinding/global.h
+++ b/sources/shiboken6/tests/minimalbinding/global.h
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "obj.h"
+#include "containeruser.h"
#include "val.h"
#include "minbool.h"
#include "listuser.h"
+#include "spanuser.h"
#include "typedef.h"
diff --git a/sources/shiboken6/tests/minimalbinding/listuser_test.py b/sources/shiboken6/tests/minimalbinding/listuser_test.py
index fc108950f..b30bb653a 100644
--- a/sources/shiboken6/tests/minimalbinding/listuser_test.py
+++ b/sources/shiboken6/tests/minimalbinding/listuser_test.py
@@ -32,7 +32,7 @@ class ExtListUser(ListUser):
return [not mb1, not mb2]
def oredMinBoolList(self, minBoolList):
- return not reduce(lambda a, b: a|b, minBoolList)
+ return not reduce(lambda a, b: a | b, minBoolList)
def createValList(self, num):
return [Val(i) for i in range(0, num * 2, 2)]
@@ -95,8 +95,14 @@ class IntListConversionTest(unittest.TestCase):
def testSumIntList(self):
lu = ListUser()
lst = range(4)
- self.assertEqual(lu.sumIntList(lst), sum(lst))
- self.assertEqual(lu.callSumIntList(lst), sum(lst))
+ expected = sum(lst)
+ self.assertEqual(lu.sumIntList(lst), expected)
+ self.assertEqual(lu.callSumIntList(lst), expected)
+ self.assertEqual(lu.sumIntListDefaultParam(lst), expected)
+ self.assertEqual(lu.sumIntListDefaultParamConstRef(lst), expected)
+ # PYSIDE-2454: Check container default parameters (1,2,3)
+ self.assertEqual(lu.sumIntListDefaultParam(), 6)
+ self.assertEqual(lu.sumIntListDefaultParamConstRef(), 6)
def testSumIntListFromExtendedClass(self):
lu = ExtListUser()
@@ -297,14 +303,16 @@ class ListOfIntListConversionTest(unittest.TestCase):
def testSumListOfIntListsFromExtendedClass(self):
lu = ExtListUser()
lst = [range(4)] * 4
- self.assertEqual(lu.sumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4]) * 2)
- self.assertEqual(lu.callSumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4]) * 2)
+ self.assertEqual(lu.sumListOfIntLists(lst),
+ sum([sum(line) for line in [range(4)] * 4]) * 2)
+ self.assertEqual(lu.callSumListOfIntLists(lst),
+ sum([sum(line) for line in [range(4)] * 4]) * 2)
def testOpaqueContainer(self):
lu = ListUser()
# Set via Python
- python_list = [1,2]
+ python_list = [1, 2]
lu.setStdIntList(python_list)
self.assertEqual(len(lu.m_stdIntList), 2)
self.assertEqual(lu.m_stdIntList[0], 1)
@@ -325,8 +333,8 @@ class ListOfIntListConversionTest(unittest.TestCase):
self.assertEqual(lu.m_stdIntList[2], 5)
# Access list via getter
- l = lu.getIntList()
- l.append(6)
+ il = lu.getIntList()
+ il.append(6)
self.assertEqual(len(lu.m_stdIntList), 4)
self.assertEqual(lu.m_stdIntList[3], 6)
diff --git a/sources/shiboken6/tests/minimalbinding/minbool_test.py b/sources/shiboken6/tests/minimalbinding/minbool_test.py
index 331b410b3..d9ce0eac0 100644
--- a/sources/shiboken6/tests/minimalbinding/minbool_test.py
+++ b/sources/shiboken6/tests/minimalbinding/minbool_test.py
@@ -13,32 +13,34 @@ init_paths()
from minimal import MinBoolUser
+
class DerivedMinBoolUser (MinBoolUser):
def returnMyselfVirtual(self):
return MinBoolUser()
+
class MinBoolTest(unittest.TestCase):
def testMinBoolUser(self):
mbuTrue = MinBoolUser()
mbuFalse = MinBoolUser()
mbuTrue.setMinBool(True)
- self.assertEqual(mbuFalse.minBool(), False)
- self.assertEqual(mbuTrue.minBool(), True)
- self.assertEqual(mbuTrue.callInvertedMinBool(), False)
+ self.assertFalse(mbuFalse.minBool())
+ self.assertTrue(mbuTrue.minBool())
+ self.assertFalse(mbuTrue.callInvertedMinBool())
- self.assertEqual(mbuTrue.minBool() == True, True)
- self.assertEqual(False == mbuFalse.minBool(), True)
- self.assertEqual(mbuTrue.minBool() == mbuFalse.minBool(), False)
+ self.assertTrue(mbuTrue.minBool())
+ self.assertFalse(mbuFalse.minBool())
+ self.assertTrue(mbuTrue.minBool() != mbuFalse.minBool())
- self.assertEqual(mbuFalse.minBool() != True, True)
- self.assertEqual(True != mbuFalse.minBool(), True)
- self.assertEqual(mbuTrue.minBool() != mbuFalse.minBool(), True)
+ self.assertFalse(mbuFalse.minBool())
+ self.assertFalse(mbuFalse.minBool())
+ self.assertTrue(mbuTrue.minBool() != mbuFalse.minBool())
def testVirtuals(self):
dmbu = DerivedMinBoolUser()
self.assertEqual(dmbu.invertedMinBool(), True)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
index 85b139676..101567070 100644
--- a/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
+++ b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers
diff --git a/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject b/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject
new file mode 100644
index 000000000..ab19dc443
--- /dev/null
+++ b/sources/shiboken6/tests/minimalbinding/minimalbinding.pyproject
@@ -0,0 +1,10 @@
+{
+ "files": ["brace_pattern_test.py",
+ "containeruser_test.py",
+ "listuser_test.py",
+ "minbool_test.py",
+ "obj_test.py",
+ "typedef_test.py",
+ "val_test.py",
+ "typesystem_minimal.xml"]
+}
diff --git a/sources/shiboken6/tests/minimalbinding/obj_test.py b/sources/shiboken6/tests/minimalbinding/obj_test.py
index 0d8a2dced..e873845de 100644
--- a/sources/shiboken6/tests/minimalbinding/obj_test.py
+++ b/sources/shiboken6/tests/minimalbinding/obj_test.py
@@ -12,6 +12,7 @@ from shiboken_paths import init_paths
init_paths()
from minimal import Obj
+
class ExtObj(Obj):
def __init__(self, objId):
Obj.__init__(self, objId)
@@ -91,4 +92,3 @@ class ObjTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/minimalbinding/spanuser_test.py b/sources/shiboken6/tests/minimalbinding/spanuser_test.py
new file mode 100644
index 000000000..6db6aa616
--- /dev/null
+++ b/sources/shiboken6/tests/minimalbinding/spanuser_test.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from shiboken_paths import init_paths
+init_paths()
+
+from minimal import SpanUser
+
+
+class IntSpanTest(unittest.TestCase):
+
+ def testCreateIntSpan(self):
+ if not SpanUser.enabled():
+ return
+ expected = [1, 2, 3]
+ self.assertEqual(SpanUser.getIntSpan3(), expected)
+ self.assertEqual(SpanUser.getIntSpan(), expected)
+ self.assertEqual(SpanUser.getConstIntSpan3(), expected)
+
+ self.assertEqual(SpanUser.sumIntSpan3(expected), 6)
+ self.assertEqual(SpanUser.sumIntSpan(expected), 6)
+ self.assertEqual(SpanUser.sumConstIntSpan3(expected), 6)
+
+ def testSpanOpaqueContainer(self):
+ if not SpanUser.enabled():
+ return
+ oc = SpanUser.getIntSpan3_OpaqueContainer() # 1,2,3
+ oc[1] = 10
+ oc = SpanUser.getIntSpan3_OpaqueContainer()
+ # note: This converts to std::vector
+ self.assertEqual(SpanUser.sumIntSpan3(oc), 14)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken6/tests/minimalbinding/typedef_test.py b/sources/shiboken6/tests/minimalbinding/typedef_test.py
index 1d878be30..c2fc8fc12 100644
--- a/sources/shiboken6/tests/minimalbinding/typedef_test.py
+++ b/sources/shiboken6/tests/minimalbinding/typedef_test.py
@@ -2,7 +2,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-from functools import reduce
import os
import sys
import unittest
@@ -11,7 +10,9 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from minimal import *
+from minimal import (arrayFunc, arrayFuncInt, arrayFuncIntReturn,
+ arrayFuncIntReturnTypedef, arrayFuncIntTypedef,
+ arrayFuncReturn, arrayFuncReturnTypedef, arrayFuncTypedef)
try:
import numpy as np
@@ -31,29 +32,37 @@ class TypedefTest(unittest.TestCase):
self.assertTrue(arrayFuncInt(none), "None is empty, arrayFuncInt should return true")
self.assertFalse(arrayFuncInt(full), "Full is NOT empty, arrayFuncInt should return false")
- self.assertTrue(arrayFuncInt(np.array(none)), "None is empty, arrayFuncInt should return true")
- self.assertFalse(arrayFuncInt(np.array(full)), "Full is NOT empty, arrayFuncInt should return false")
+ self.assertTrue(arrayFuncInt(np.array(none)),
+ "None is empty, arrayFuncInt should return true")
+ self.assertFalse(arrayFuncInt(np.array(full)),
+ "Full is NOT empty, arrayFuncInt should return false")
def test_arrayFuncIntTypedef(self):
none = ()
full = (1, 2, 3)
- self.assertTrue(arrayFuncIntTypedef(none), "None is empty, arrayFuncIntTypedef should return true")
- self.assertFalse(arrayFuncIntTypedef(full), "Full is NOT empty, arrayFuncIntTypedef should return false")
+ self.assertTrue(arrayFuncIntTypedef(none),
+ "None is empty, arrayFuncIntTypedef should return true")
+ self.assertFalse(arrayFuncIntTypedef(full),
+ "Full is NOT empty, arrayFuncIntTypedef should return false")
- self.assertTrue(arrayFuncIntTypedef(np.array(none)), "None is empty, arrayFuncIntTypedef should return true")
- self.assertFalse(arrayFuncIntTypedef(np.array(full)), "Full is NOT empty, arrayFuncIntTypedef should return false")
+ self.assertTrue(arrayFuncIntTypedef(np.array(none)),
+ "None is empty, arrayFuncIntTypedef should return true")
+ self.assertFalse(arrayFuncIntTypedef(np.array(full)),
+ "Full is NOT empty, arrayFuncIntTypedef should return false")
def test_arrayFuncIntReturn(self):
none = arrayFuncIntReturn(0)
full = arrayFuncIntReturn(self.the_size)
self.assertTrue((len(none) == 0), "none should be empty")
- self.assertTrue((len(full) == self.the_size), "full should have " + str(self.the_size) + " elements")
+ self.assertTrue((len(full) == self.the_size),
+ f"full should have {self.the_size} elements")
def test_arrayFuncIntReturnTypedef(self):
none = arrayFuncIntReturnTypedef(0)
full = arrayFuncIntReturnTypedef(self.the_size)
self.assertTrue((len(none) == 0), "none should be empty")
- self.assertTrue((len(full) == self.the_size), "full should have " + str(self.the_size) + " elements")
+ self.assertTrue((len(full) == self.the_size),
+ f"full should have {self.the_size} elements")
def test_arrayFunc(self):
none = ()
@@ -62,30 +71,37 @@ class TypedefTest(unittest.TestCase):
self.assertFalse(arrayFunc(full), "Full is NOT empty, arrayFunc should return false")
self.assertTrue(arrayFunc(np.array(none)), "None is empty, arrayFunc should return true")
- self.assertFalse(arrayFunc(np.array(full)), "Full is NOT empty, arrayFunc should return false")
+ self.assertFalse(arrayFunc(np.array(full)),
+ "Full is NOT empty, arrayFunc should return false")
def test_arrayFuncTypedef(self):
none = ()
full = (1, 2, 3)
- self.assertTrue(arrayFuncTypedef(none), "None is empty, arrayFuncTypedef should return true")
- self.assertFalse(arrayFuncTypedef(full), "Full is NOT empty, arrayFuncTypedef should return false")
+ self.assertTrue(arrayFuncTypedef(none),
+ "None is empty, arrayFuncTypedef should return true")
+ self.assertFalse(arrayFuncTypedef(full),
+ "Full is NOT empty, arrayFuncTypedef should return false")
- self.assertTrue(arrayFuncTypedef(np.array(none)), "None is empty, arrayFuncTypedef should return true")
- self.assertFalse(arrayFuncTypedef(np.array(full)), "Full is NOT empty, arrayFuncTypedef should return false")
+ self.assertTrue(arrayFuncTypedef(np.array(none)),
+ "None is empty, arrayFuncTypedef should return true")
+ self.assertFalse(arrayFuncTypedef(np.array(full)),
+ "Full is NOT empty, arrayFuncTypedef should return false")
def test_arrayFuncReturn(self):
none = arrayFuncReturn(0)
full = arrayFuncReturn(self.the_size)
self.assertTrue((len(none) == 0), "none should be empty")
- self.assertTrue((len(full) == self.the_size), "full should have " + str(self.the_size) + " elements")
+ self.assertTrue((len(full) == self.the_size),
+ f"full should have {self.the_size} elements")
def test_arrayFuncReturnTypedef(self):
none = arrayFuncReturnTypedef(0)
full = arrayFuncReturnTypedef(self.the_size)
self.assertTrue((len(none) == 0), "none should be empty")
- self.assertTrue((len(full) == self.the_size), "full should have " + str(self.the_size) + " elements")
+ self.assertTrue((len(full) == self.the_size),
+ f"full should have {self.the_size} elements")
if __name__ == '__main__':
- if np != None:
+ if np is not None:
unittest.main()
diff --git a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
index 3fac1b2b3..e18bf8686 100644
--- a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
+++ b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
@@ -15,20 +15,15 @@
</conversion-rule>
</primitive-type>
- <container-type name="std::list" type="list"
- opaque-containers="int:StdIntList">
- <include file-name="list" location="global"/>
- <conversion-rule>
- <native-to-target>
- <insert-template name="shiboken_conversion_cppsequence_to_pylist"/>
- </native-to-target>
- <target-to-native>
- <add-conversion type="PySequence">
- <insert-template name="shiboken_conversion_pyiterable_to_cppsequentialcontainer"/>
- </add-conversion>
- </target-to-native>
- </conversion-rule>
- </container-type>
+ <opaque-container name="std::list" opaque-containers="int:StdIntList"/>
+
+ <opaque-container name="std::vector" opaque-containers="int:StdIntVector"/>
+
+ <opaque-container name="std::array" opaque-containers="int,3:StdIntArray"/>
+
+ <?if c++20?> <!-- FIXME PYSIDE 7: Remove "if" -->
+ <opaque-container name="std::span" opaque-containers="int,3:StdIntSpan3"/>
+ <?endif?>
<object-type name="Obj"/>
<value-type name="Val">
@@ -47,8 +42,32 @@
</modify-argument>
</modify-function>
</value-type>
+
+ <value-type name="SpanUser">
+ <?if c++20?> <!-- FIXME PYSIDE 7: Remove "if" -->
+ <modify-function signature="getIntSpan3_OpaqueContainer()">
+ <modify-argument index="return">
+ <replace-type modified-type="StdIntSpan3"/>
+ </modify-argument>
+ </modify-function>
+ <?endif?>
+ </value-type>
+
<value-type name="MinBoolUser"/>
+ <value-type name="ContainerUser">
+ <modify-function signature="intVector()">
+ <modify-argument index="return">
+ <replace-type modified-type="StdIntVector"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="intArray()">
+ <modify-argument index="return">
+ <replace-type modified-type="StdIntArray"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
<!-- Test wrapping of a typedef -->
<function signature="arrayFuncInt(std::vector&lt;int&gt;)" />
<!-- Note manual expansion of the typedef -->
diff --git a/sources/shiboken6/tests/minimalbinding/val_test.py b/sources/shiboken6/tests/minimalbinding/val_test.py
index 6403b5f14..b8225a247 100644
--- a/sources/shiboken6/tests/minimalbinding/val_test.py
+++ b/sources/shiboken6/tests/minimalbinding/val_test.py
@@ -92,4 +92,3 @@ class ValTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/CMakeLists.txt b/sources/shiboken6/tests/otherbinding/CMakeLists.txt
index e516371b9..2172593d3 100644
--- a/sources/shiboken6/tests/otherbinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/otherbinding/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(other)
set(other_TYPESYSTEM
@@ -22,13 +25,19 @@ ${CMAKE_CURRENT_BINARY_DIR}/other/valuewithunitintmillimeter_wrapper.cpp
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/other-binding.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt" @ONLY)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
add_custom_command(
-OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
-BYPRODUCTS ${other_SRC}
-COMMAND Shiboken6::shiboken6 --project-file=${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt ${GENERATOR_EXTRA_FLAGS}
-DEPENDS ${other_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
-WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-COMMENT "Running generator for 'other' test binding..."
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${other_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --project-file=${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt
+ ${GENERATOR_EXTRA_FLAGS}
+ DEPENDS ${other_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for 'other' test binding..."
)
add_library(other MODULE ${other_SRC})
diff --git a/sources/shiboken6/tests/otherbinding/collector_external_operator_test.py b/sources/shiboken6/tests/otherbinding/collector_external_operator_test.py
index ab9a67345..2ba21653d 100644
--- a/sources/shiboken6/tests/otherbinding/collector_external_operator_test.py
+++ b/sources/shiboken6/tests/otherbinding/collector_external_operator_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import Collector, ObjectType
from other import OtherObjectType
+
class CollectorOtherObjectType(unittest.TestCase):
'''Test cases for Collector << OtherObjectType'''
@@ -33,6 +34,6 @@ class CollectorOtherObjectType(unittest.TestCase):
collector << obj
self.assertEqual(collector.items()[0], obj.identifier() * 2)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py b/sources/shiboken6/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py
index 220cd3c98..bd00b5892 100644
--- a/sources/shiboken6/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py
+++ b/sources/shiboken6/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py
@@ -18,8 +18,10 @@ init_paths()
from sample import NoImplicitConversion
from other import ExtendsNoImplicitConversion
+
class ConversionOperatorForClassWithoutImplicitConversionsTest(unittest.TestCase):
- '''Tests calling NoImplicitConversion constructor using a ExtendsNoImplicitConversion parameter.'''
+ '''Tests calling NoImplicitConversion constructor using a
+ ExtendsNoImplicitConversion parameter.'''
def testNoImplicitConversion(self):
'''Basic test to see if the NoImplicitConversion is Ok.'''
@@ -27,27 +29,33 @@ class ConversionOperatorForClassWithoutImplicitConversionsTest(unittest.TestCase
# NoImplicitConversion.receivesNoImplicitConversionByValue(NoImplicitConversion)
self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByValue(obj))
# NoImplicitConversion.receivesNoImplicitConversionByPointer(NoImplicitConversion*)
- self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByPointer(obj))
+ self.assertEqual(obj.objId(),
+ NoImplicitConversion.receivesNoImplicitConversionByPointer(obj))
# NoImplicitConversion.receivesNoImplicitConversionByReference(NoImplicitConversion&)
- self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByReference(obj))
+ self.assertEqual(obj.objId(),
+ NoImplicitConversion.receivesNoImplicitConversionByReference(obj))
def testPassingExtendsNoImplicitConversionAsNoImplicitConversionByValue(self):
- '''Gives an ExtendsNoImplicitConversion object to a function expecting a NoImplicitConversion, passing by value.'''
+ '''Gives an ExtendsNoImplicitConversion object to a function expecting a
+ NoImplicitConversion, passing by value.'''
obj = ExtendsNoImplicitConversion(123)
self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByValue(obj))
def testPassingExtendsNoImplicitConversionAsNoImplicitConversionByReference(self):
- '''Gives an ExtendsNoImplicitConversion object to a function expecting a NoImplicitConversion, passing by reference.'''
+ '''Gives an ExtendsNoImplicitConversion object to a function expecting a
+ NoImplicitConversion, passing by reference.'''
obj = ExtendsNoImplicitConversion(123)
- self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByReference(obj))
+ self.assertEqual(obj.objId(),
+ NoImplicitConversion.receivesNoImplicitConversionByReference(obj))
def testPassingExtendsNoImplicitConversionAsNoImplicitConversionByPointer(self):
- '''Gives an ExtendsNoImplicitConversion object to a function expecting a NoImplicitConversion, passing by pointer.
- This should not be accepted, since pointers should not be converted.'''
+ '''Gives an ExtendsNoImplicitConversion object to a function expecting
+ a NoImplicitConversion, passing by pointer. This should not be
+ accepted, since pointers should not be converted.'''
obj = ExtendsNoImplicitConversion(123)
- self.assertRaises(TypeError, NoImplicitConversion.receivesNoImplicitConversionByPointer, obj)
+ self.assertRaises(TypeError,
+ NoImplicitConversion.receivesNoImplicitConversionByPointer, obj)
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/extended_multiply_operator_test.py b/sources/shiboken6/tests/otherbinding/extended_multiply_operator_test.py
index 169f5259d..abbef6231 100644
--- a/sources/shiboken6/tests/otherbinding/extended_multiply_operator_test.py
+++ b/sources/shiboken6/tests/otherbinding/extended_multiply_operator_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import Point
from other import Number
+
class PointOperationsWithNumber(unittest.TestCase):
'''Test cases for libsample's Point multiply operator defined in libother module.'''
@@ -39,6 +40,6 @@ class PointOperationsWithNumber(unittest.TestCase):
num = Number(11)
self.assertEqual(pt * num.value(), pt * 11)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/module_reload_test.py b/sources/shiboken6/tests/otherbinding/module_reload_test.py
index 5be2b4191..bde2f5236 100644
--- a/sources/shiboken6/tests/otherbinding/module_reload_test.py
+++ b/sources/shiboken6/tests/otherbinding/module_reload_test.py
@@ -21,6 +21,7 @@ dst = workdir / 'test_module.py'
shutil.copyfile(src, dst)
sys.path.append(os.fspath(workdir))
+
class TestModuleReloading(unittest.TestCase):
def testModuleReloading(self):
@@ -32,5 +33,6 @@ class TestModuleReloading(unittest.TestCase):
reload(test_module)
self.assertFalse(oldObject is test_module.obj)
+
if __name__ == "__main__":
unittest.main()
diff --git a/sources/shiboken6/tests/otherbinding/new_ctor_operator_test.py b/sources/shiboken6/tests/otherbinding/new_ctor_operator_test.py
index 5e3536c93..d6c356436 100644
--- a/sources/shiboken6/tests/otherbinding/new_ctor_operator_test.py
+++ b/sources/shiboken6/tests/otherbinding/new_ctor_operator_test.py
@@ -2,7 +2,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-'''Tests calling Str constructor using a Number parameter, being that number defines a cast operator to Str.'''
+'''Tests calling Str constructor using a Number parameter, being that number defines
+ a cast operator to Str.'''
import os
import sys
@@ -16,8 +17,10 @@ init_paths()
from sample import Str
from other import Number
+
class NewCtorOperatorTest(unittest.TestCase):
- '''Tests calling Str constructor using a Number parameter, being that number defines a cast operator to Str.'''
+ '''Tests calling Str constructor using a Number parameter, being that number
+ defines a cast operator to Str.'''
def testNumber(self):
'''Basic test to see if the Number class is Ok.'''
@@ -29,8 +32,8 @@ class NewCtorOperatorTest(unittest.TestCase):
'''Try to build a Str from 'sample' module with a Number argument from 'other' module.'''
value = 123
num = Number(value)
- string = Str(num)
+ string = Str(num) # noqa: F841
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/objtypehashes_test.py b/sources/shiboken6/tests/otherbinding/objtypehashes_test.py
index d2c441058..d2cd7de5b 100644
--- a/sources/shiboken6/tests/otherbinding/objtypehashes_test.py
+++ b/sources/shiboken6/tests/otherbinding/objtypehashes_test.py
@@ -9,10 +9,10 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
-from other import *
+from sample import HandleHolder
from shiboken6 import Shiboken
+
class TestHashFuncs (unittest.TestCase):
def testIt(self):
@@ -30,6 +30,5 @@ class TestHashFuncs (unittest.TestCase):
self.assertEqual(hash1_2, hash1)
-
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/otherbinding/other-binding.txt.in b/sources/shiboken6/tests/otherbinding/other-binding.txt.in
index dbe935a9f..d85f6030a 100644
--- a/sources/shiboken6/tests/otherbinding/other-binding.txt.in
+++ b/sources/shiboken6/tests/otherbinding/other-binding.txt.in
@@ -17,4 +17,4 @@ typesystem-path = @sample_SOURCE_DIR@
typesystem-path = @smart_SOURCE_DIR@
enable-parent-ctor-heuristic
-
+lean-headers
diff --git a/sources/shiboken6/tests/otherbinding/otherbinding.pyproject b/sources/shiboken6/tests/otherbinding/otherbinding.pyproject
new file mode 100644
index 000000000..d1bbee11e
--- /dev/null
+++ b/sources/shiboken6/tests/otherbinding/otherbinding.pyproject
@@ -0,0 +1,17 @@
+{
+ "files": ["collector_external_operator_test.py",
+ "conversion_operator_for_class_without_implicit_conversions_test.py",
+ "extended_multiply_operator_test.py",
+ "module_reload_test.py",
+ "new_ctor_operator_test.py",
+ "objtypehashes_test.py",
+ "otherderived_test.py",
+ "othertypesystypedef_test.py",
+ "signature_test.py",
+ "smartptr_test.py",
+ "test_module_template.py",
+ "typediscovery_test.py",
+ "usersprimitivefromothermodule_test.py",
+ "wrongctor_test.py",
+ "typesystem_other.xml"]
+}
diff --git a/sources/shiboken6/tests/otherbinding/otherderived_test.py b/sources/shiboken6/tests/otherbinding/otherderived_test.py
index 1b876e1ed..459f474f1 100644
--- a/sources/shiboken6/tests/otherbinding/otherderived_test.py
+++ b/sources/shiboken6/tests/otherbinding/otherderived_test.py
@@ -17,6 +17,7 @@ init_paths()
from sample import Abstract, Derived
from other import OtherDerived, Number
+
class Multiple(Derived, Number):
def __init__(self):
Derived.__init__(self, 42)
@@ -25,6 +26,7 @@ class Multiple(Derived, Number):
def testCall(self):
return True
+
class OtherDeviant(OtherDerived):
def __init__(self):
OtherDerived.__init__(self)
@@ -40,6 +42,7 @@ class OtherDeviant(OtherDerived):
def className(self):
return 'OtherDeviant'
+
class MultipleTest(unittest.TestCase):
'''Test case for Multiple derived class'''
@@ -58,6 +61,7 @@ class MultipleTest(unittest.TestCase):
self.assertTrue(o.value(), 42)
self.assertTrue(o.testCall())
+
class OtherDerivedTest(unittest.TestCase):
'''Test case for OtherDerived class'''
@@ -68,13 +72,15 @@ class OtherDerivedTest(unittest.TestCase):
self.assertTrue(inherited_methods.issubset(dir(OtherDerived)))
def testReimplementedPureVirtualMethodCall(self):
- '''Test if a Python override of a implemented pure virtual method is correctly called from C++.'''
+ '''Test if a Python override of a implemented pure virtual method is
+ correctly called from C++.'''
d = OtherDeviant()
d.callPureVirtual()
self.assertTrue(d.pure_virtual_called)
def testReimplementedVirtualMethodCall(self):
- '''Test if a Python override of a reimplemented virtual method is correctly called from C++.'''
+ '''Test if a Python override of a reimplemented virtual method is
+ correctly called from C++.'''
d = OtherDeviant()
d.callUnpureVirtual()
self.assertTrue(d.unpure_virtual_called)
@@ -86,7 +92,8 @@ class OtherDerivedTest(unittest.TestCase):
self.assertEqual(d.getClassName(), 'OtherDerived')
def testReimplementedVirtualMethodCallReturningString(self):
- '''Test if a Python override of a reimplemented virtual method is correctly called from C++.'''
+ '''Test if a Python override of a reimplemented virtual method is
+ correctly called from C++.'''
d = OtherDeviant()
self.assertEqual(d.className(), 'OtherDeviant')
self.assertEqual(d.getClassName(), 'OtherDeviant')
@@ -97,6 +104,6 @@ class OtherDerivedTest(unittest.TestCase):
d = OtherDerived(objId)
self.assertEqual(Abstract.getObjectId(d), objId)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/otherbinding/othertypesystypedef_test.py b/sources/shiboken6/tests/otherbinding/othertypesystypedef_test.py
index 9ac2456c0..198c71693 100644
--- a/sources/shiboken6/tests/otherbinding/othertypesystypedef_test.py
+++ b/sources/shiboken6/tests/otherbinding/othertypesystypedef_test.py
@@ -13,8 +13,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from other import (OtherValueWithUnitUser, ValueWithUnitIntInch,
- ValueWithUnitIntMillimeter)
+from other import (OtherValueWithUnitUser, ValueWithUnitIntMillimeter)
from sample import (ValueWithUnitDoubleMillimeter)
diff --git a/sources/shiboken6/tests/otherbinding/signature_test.py b/sources/shiboken6/tests/otherbinding/signature_test.py
index 26fdde442..8db3e566b 100644
--- a/sources/shiboken6/tests/otherbinding/signature_test.py
+++ b/sources/shiboken6/tests/otherbinding/signature_test.py
@@ -16,9 +16,6 @@ init_paths()
from other import OtherObjectType
from shiboken_test_helper import objectFullname
-from shiboken6 import Shiboken
-_init_pyside_extension() # trigger bootstrap
-
from shibokensupport.signature import get_signature
@@ -30,7 +27,7 @@ class SignatureTest(unittest.TestCase):
def testNamespaceFromOtherModule(self):
argType = get_signature(OtherObjectType.enumAsInt).parameters["value"].annotation
self.assertEqual(objectFullname(argType),
- "sample.SampleNamespace.SomeClass.PublicScopedEnum")
+ "sample.SampleNamespace.SomeClass.PublicScopedEnum")
if __name__ == '__main__':
diff --git a/sources/shiboken6/tests/otherbinding/smartptr_test.py b/sources/shiboken6/tests/otherbinding/smartptr_test.py
index 6479e6337..fd5c7fa09 100644
--- a/sources/shiboken6/tests/otherbinding/smartptr_test.py
+++ b/sources/shiboken6/tests/otherbinding/smartptr_test.py
@@ -13,8 +13,6 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from smart import Integer
-from sample import Str
from other import SmartPtrTester
diff --git a/sources/shiboken6/tests/otherbinding/star_import_test.py b/sources/shiboken6/tests/otherbinding/star_import_test.py
new file mode 100644
index 000000000..4b5f1d270
--- /dev/null
+++ b/sources/shiboken6/tests/otherbinding/star_import_test.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+"""PYSIDE-2404: Test whether star imports work as they require special handling
+ by the lazy initialization."""
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from shiboken_paths import init_paths
+init_paths()
+
+SHIBOKEN_NAME = "shiboken6.Shiboken"
+MINIMAL_NAME = "minimal"
+OTHER_NAME = "other"
+
+shiboken_loaded = 1 if sys.modules.get(SHIBOKEN_NAME) else 0
+minimal_loaded = 1 if sys.modules.get(MINIMAL_NAME) else 0
+other_loaded = 1 if sys.modules.get(OTHER_NAME) else 0
+
+from minimal import * # noqa: F403
+
+shiboken_loaded += 2 if sys.modules.get(SHIBOKEN_NAME) else 0
+minimal_loaded += 2 if sys.modules.get(MINIMAL_NAME) else 0
+other_loaded += 2 if sys.modules.get(OTHER_NAME) else 0
+
+from other import Number # noqa: F403
+from other import * # noqa: F403
+
+shiboken_loaded += 4 if sys.modules.get(SHIBOKEN_NAME) else 0
+minimal_loaded += 4 if sys.modules.get(MINIMAL_NAME) else 0
+other_loaded = +4 if sys.modules.get(OTHER_NAME) else 0
+
+import shiboken6.Shiboken # noqa: F401 F403
+
+shiboken_loaded += 8 if sys.modules.get(SHIBOKEN_NAME) else 0
+
+
+class ValTest(unittest.TestCase):
+
+ def test(self):
+ val_id = 123
+ val = Val(val_id) # noqa: F405
+ self.assertEqual(val.valId(), val_id)
+
+
+class Simple(Number):
+
+ def __init__(self):
+ Number.__init__(self, 42)
+
+
+class OtherTest(unittest.TestCase):
+
+ def testConstructor(self):
+ o = Simple()
+ self.assertTrue(isinstance(o, Number))
+
+
+class StarImportTest(unittest.TestCase):
+ """
+ This test is meant for Lazy Init.
+ We explicitly choose modules which are able to lazy load.
+
+ The ValTest:
+ ------------
+ We load something with `import *`.
+ There is no module from our known ones imported.
+ This means we need stack introspection to find out that this was
+ a star import and we must disable lazyness.
+
+ The OtherTest:
+ --------------
+ We load something normally that should be lazy.
+ After that, we follow with a star import.
+ Now the stack introspection does not work, because the loading is
+ cached. The first import did a lazy load. The following star import
+ needs to undo the lazyness. But now we have a redirected import.
+
+ All tests simply check if the objects are real and not just names.
+ The <module>_loaded tests prevend upcoming internal dependencies.
+
+ To make sure that Shiboken is really not involved, it is checked
+ and really imported afterwards (ensuring nothing is misspelled).
+ """
+
+ def testStar(self):
+ self.assertEqual(other_loaded, 4)
+ self.assertEqual(minimal_loaded, 6)
+ self.assertEqual(shiboken_loaded, 14)
+ # Interesting effect: Did not expect that shiboken is loaded at all.
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken6/tests/otherbinding/test_module_template.py b/sources/shiboken6/tests/otherbinding/test_module_template.py
index 183ba9fe5..36ab43ae3 100644
--- a/sources/shiboken6/tests/otherbinding/test_module_template.py
+++ b/sources/shiboken6/tests/otherbinding/test_module_template.py
@@ -1,13 +1,22 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-from other import *
-from sample import *
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from shiboken_paths import init_paths
+init_paths()
+
+from other import OtherObjectType
+from sample import ObjectType
class MyObjectType(ObjectType):
pass
+
class MyOtherObjectType(OtherObjectType):
value = 10
diff --git a/sources/shiboken6/tests/otherbinding/typediscovery_test.py b/sources/shiboken6/tests/otherbinding/typediscovery_test.py
index 51fc7c01b..39dc5cf0f 100644
--- a/sources/shiboken6/tests/otherbinding/typediscovery_test.py
+++ b/sources/shiboken6/tests/otherbinding/typediscovery_test.py
@@ -13,9 +13,11 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import Abstract, Base1, Derived, MDerived1, MDerived3, SonOfMDerived1
+from sample import (Abstract, Base1, Derived,
+ MDerived1, SonOfMDerived1, MDerived3)
from other import OtherMultipleDerived
+
class TypeDiscoveryTest(unittest.TestCase):
def testPureVirtualsOfImpossibleTypeDiscovery(self):
@@ -29,18 +31,23 @@ class TypeDiscoveryTest(unittest.TestCase):
self.assertEqual(type(a), Derived)
def testMultipleInheritance(self):
- obj = OtherMultipleDerived.createObject("Base1");
+ obj = OtherMultipleDerived.createObject("Base1")
self.assertEqual(type(obj), Base1)
- # PYSIDE-868: In case of multiple inheritance, a factory
+ # PYSIDE-868: In case of single line direct inheritance,
+ # a factory function will return the class wrapper
+ # of the derived class.
+ obj = OtherMultipleDerived.createObject("MDerived1")
+ self.assertEqual(type(obj), MDerived1)
+ obj = OtherMultipleDerived.createObject("SonOfMDerived1")
+ self.assertEqual(type(obj), SonOfMDerived1)
+ obj = OtherMultipleDerived.createObject("MDerived3")
+ self.assertEqual(type(obj), MDerived3)
+ # PYSIDE-868: OtherMultipleDerived inherits
+ # OtherBase, Base1. In this case, a factory
# function will return the base class wrapper.
- obj = OtherMultipleDerived.createObject("MDerived1");
- self.assertEqual(type(obj), Base1)
- obj = OtherMultipleDerived.createObject("SonOfMDerived1");
- self.assertEqual(type(obj), Base1)
- obj = OtherMultipleDerived.createObject("MDerived3");
- self.assertEqual(type(obj), Base1)
- obj = OtherMultipleDerived.createObject("OtherMultipleDerived");
+ obj = OtherMultipleDerived.createObject("OtherMultipleDerived")
self.assertEqual(type(obj), Base1)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/otherbinding/typesystem_other.xml b/sources/shiboken6/tests/otherbinding/typesystem_other.xml
index 4081548fc..ade1c8bad 100644
--- a/sources/shiboken6/tests/otherbinding/typesystem_other.xml
+++ b/sources/shiboken6/tests/otherbinding/typesystem_other.xml
@@ -17,8 +17,4 @@
<typedef-type name="ValueWithUnitIntInch" source="ValueWithUnit&lt;int,LengthUnit::Inch&gt;"/>
<typedef-type name="ValueWithUnitIntMillimeter" source="ValueWithUnit&lt;int,LengthUnit::Millimeter&gt;"/>
<value-type name="OtherValueWithUnitUser"/>
-
- <suppress-warning text="signature 'operator!=(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
- <suppress-warning text="signature 'operator+(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
- <suppress-warning text="signature 'operator==(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
</typesystem>
diff --git a/sources/shiboken6/tests/otherbinding/usersprimitivefromothermodule_test.py b/sources/shiboken6/tests/otherbinding/usersprimitivefromothermodule_test.py
index b464fa566..15a988326 100644
--- a/sources/shiboken6/tests/otherbinding/usersprimitivefromothermodule_test.py
+++ b/sources/shiboken6/tests/otherbinding/usersprimitivefromothermodule_test.py
@@ -14,6 +14,7 @@ from shiboken_paths import init_paths
init_paths()
from other import Number
+
class UserDefinedPrimitiveTypeFromRequiredModuleTest(unittest.TestCase):
def testUsersPrimitiveFromRequiredModuleAsArgument(self):
@@ -28,5 +29,6 @@ class UserDefinedPrimitiveTypeFromRequiredModuleTest(unittest.TestCase):
cpx = number.toComplex()
self.assertEqual(number.value(), int(cpx.real))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/otherbinding/wrongctor_test.py b/sources/shiboken6/tests/otherbinding/wrongctor_test.py
index 9aacfa9ac..b9251b428 100644
--- a/sources/shiboken6/tests/otherbinding/wrongctor_test.py
+++ b/sources/shiboken6/tests/otherbinding/wrongctor_test.py
@@ -10,17 +10,19 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
-from other import *
+from sample import Abstract, ObjectType
+from other import OtherDerived
+
class Foo(OtherDerived):
def __init__(self):
- Abstract.__init__(self, 2) # this should raise an exception
+ Abstract.__init__(self, 2) # this should raise an exception
+
class Foo2(ObjectType, OtherDerived):
def __init__(self):
ObjectType.__init__(self)
- Abstract.__init__(self, 2) # this should raise an exception
+ Abstract.__init__(self, 2) # this should raise an exception
class WrongCtorTest(unittest.TestCase):
diff --git a/sources/shiboken6/tests/qtxmltosphinx/CMakeLists.txt b/sources/shiboken6/tests/qtxmltosphinx/CMakeLists.txt
index cc73ac727..11b22f038 100644
--- a/sources/shiboken6/tests/qtxmltosphinx/CMakeLists.txt
+++ b/sources/shiboken6/tests/qtxmltosphinx/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
# Standalone-buildable
diff --git a/sources/shiboken6/tests/qtxmltosphinx/main.cpp b/sources/shiboken6/tests/qtxmltosphinx/main.cpp
index 54e516b73..27aaee7d1 100644
--- a/sources/shiboken6/tests/qtxmltosphinx/main.cpp
+++ b/sources/shiboken6/tests/qtxmltosphinx/main.cpp
@@ -13,6 +13,8 @@
#include <exception>
#include <iostream>
+using namespace Qt::StringLiterals;
+
static const char help[] = R"(QtXmlToSphinx WebXML to rst converter
A manual test for converting WebXML files to rst files for checking
@@ -89,7 +91,7 @@ int main(int argc, char *argv[])
QCommandLineParser commandLineParser;
commandLineParser.setApplicationDescription(QString::fromLatin1(help));
commandLineParser.addHelpOption();
- commandLineParser.addPositionalArgument(u"[file]"_qs, u"WebXML file to process."_qs);
+ commandLineParser.addPositionalArgument(u"[file]"_s, u"WebXML file to process."_s);
commandLineParser.process(QCoreApplication::arguments());
if (commandLineParser.positionalArguments().isEmpty())
commandLineParser.showHelp(0); // quits
diff --git a/sources/shiboken6/tests/qtxmltosphinxtest/CMakeLists.txt b/sources/shiboken6/tests/qtxmltosphinxtest/CMakeLists.txt
index 940a171b5..25074e716 100644
--- a/sources/shiboken6/tests/qtxmltosphinxtest/CMakeLists.txt
+++ b/sources/shiboken6/tests/qtxmltosphinxtest/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
project(qtxmltosphinxtest)
diff --git a/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.cpp b/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.cpp
index 963a74da7..45cecd1a1 100644
--- a/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.cpp
+++ b/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.cpp
@@ -5,9 +5,12 @@
#include "qtxmltosphinx.h"
#include <QtTest/QTest>
+#include <QtCore/QBuffer>
#include <QtCore/QDebug>
#include <QtCore/QLoggingCategory>
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcQtXmlToSphinxTest, "qt.sphinxtabletest");
// QtXmlToSphinxDocGeneratorInterface
@@ -271,6 +274,43 @@ void QtXmlToSphinxTest::testTable_data()
QTest::newRow("testRowSpan2")
<< QString::fromLatin1(xml) << QString::fromLatin1(expected);
+ // testNestedList
+ xml = R"(<table>
+ <row>
+ <item>
+ <list type="bullet">
+ <item>
+ <para>I11</para>
+ </item>
+ <item>
+ <para>I21</para>
+ </item>
+ </list>
+ </item>
+ <item>
+ <list type="bullet">
+ <item>
+ <para>I12</para>
+ </item>
+ <item>
+ <para>I22</para>
+ </item>
+ </list>
+ </item>
+ </row>
+</table>)";
+
+ expected = R"(
+ +---------+---------+
+ | * I11| * I12|
+ | * I21| * I22|
+ +---------+---------+
+
+)";
+
+ QTest::newRow("testNestedList")
+ << QString::fromLatin1(xml) << QString::fromLatin1(expected);
+
// testBrokenTable
xml = R"(<table>
<header>
@@ -344,26 +384,20 @@ void QtXmlToSphinxTest::testTable()
QCOMPARE(actual, expected);
}
-using TablePtr = QSharedPointer<QtXmlToSphinx::Table>;
+using TablePtr = std::shared_ptr<QtXmlToSphinx::Table>;
Q_DECLARE_METATYPE(TablePtr);
void QtXmlToSphinxTest::testTableFormatting_data()
{
- using TableRow = QtXmlToSphinx::TableRow;
using TableCell = QtXmlToSphinx::TableCell;
QTest::addColumn<TablePtr>("table");
QTest::addColumn<QString>("expected");
TablePtr table(new QtXmlToSphinx::Table);
- TableRow row;
- row << TableCell("item11") << TableCell("item12");
- table->appendRow(row);
- row.clear();
- row << TableCell("") << TableCell("item22");
- table->appendRow(row);
- row.clear();
+ table->appendRow({TableCell("item11"), TableCell("item12")});
+ table->appendRow({TableCell(""), TableCell("item22")});
table->normalize();
const char *expected = R"(+------+------+
@@ -377,12 +411,8 @@ void QtXmlToSphinxTest::testTableFormatting_data()
QTest::newRow("normal") << table << QString::fromLatin1(expected);
table.reset(new QtXmlToSphinx::Table);
- row << TableCell("item11") << TableCell("item12\nline2");
- table->appendRow(row);
- row.clear();
- row << TableCell("") << TableCell("item22\nline2\nline3");
- table->appendRow(row);
- row.clear();
+ table->appendRow({TableCell("item11"), TableCell("item12\nline2")});
+ table->appendRow({TableCell(""), TableCell("item22\nline2\nline3")});
table->normalize();
expected = R"(+------+------+
@@ -431,4 +461,51 @@ void QtXmlToSphinxTest::testTableFormattingIoDevice()
QCOMPARE(actual, expected);
}
+void QtXmlToSphinxTest::testSnippetExtraction_data()
+{
+ QTest::addColumn<QByteArray>("file");
+ QTest::addColumn<QLatin1StringView>("id");
+ QTest::addColumn<QString>("expected");
+
+ const char *fileCpp = R"(bla
+// ![snip1]
+snip1_line1
+// ![snip1] // ![snip2]
+snip2_line1
+snip2_line2
+// ![snip2] // ![snip3]
+)";
+
+ constexpr auto id = "snip2"_L1;
+ const QString expected = uR"(snip2_line1
+snip2_line2
+)"_s;
+
+ const char *filePython = R"(bla
+# ![snip1]
+snip1_line1
+# ![snip1] # ![snip2]
+snip2_line1
+snip2_line2
+# ![snip2] # ![snip3]
+)";
+
+ QTest::newRow("c++") << QByteArray(fileCpp) << id << expected;
+ QTest::newRow("Python") << QByteArray(filePython) << id << expected;
+}
+
+void QtXmlToSphinxTest::testSnippetExtraction()
+{
+ QFETCH(QByteArray, file);
+ QFETCH(QLatin1StringView, id);
+ QFETCH(QString, expected);
+
+ QBuffer buffer(&file);
+ QVERIFY(buffer.open(QIODevice::ReadOnly));
+ QString errorMessage;
+ QString actual = QtXmlToSphinx::readSnippet(buffer, id, &errorMessage);
+ QVERIFY2(errorMessage.isEmpty(), qPrintable(errorMessage));
+ QCOMPARE(actual, expected);
+}
+
QTEST_APPLESS_MAIN( QtXmlToSphinxTest)
diff --git a/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.h b/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.h
index 1c46789d8..0a210b7a0 100644
--- a/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.h
+++ b/sources/shiboken6/tests/qtxmltosphinxtest/qtxmltosphinxtest.h
@@ -27,6 +27,8 @@ private slots:
void testTableFormatting();
void testTableFormattingIoDevice_data();
void testTableFormattingIoDevice();
+ void testSnippetExtraction_data();
+ void testSnippetExtraction();
private:
QString transformXml(const QString &xml) const;
diff --git a/sources/shiboken6/tests/samplebinding/CMakeLists.txt b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
index 7576f6734..fc812feb8 100644
--- a/sources/shiboken6/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/samplebinding/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(sample)
set(sample_TYPESYSTEM
@@ -27,6 +30,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/customoverloadsequence_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/cvlistuser_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/cvvaluetype_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/sbkdate_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/deleteddefaultctor_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/derivedusingct_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp
@@ -106,11 +110,13 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/sample_sample_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_ctparam_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_inlinenamespace_classwithininlinenamespace_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_someclass_someinnerclass_okthisisrecursiveenough_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_someclass_someinnerclass_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_someclass_someotherinnerclass_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_someclass_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_derivedfromnamespace_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/stdcomplex_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/simplefile_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/size_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/sizef_wrapper.cpp
@@ -142,13 +148,19 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/union_wrapper.cpp
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sample-binding.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/sample-binding.txt" @ONLY)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
add_custom_command(
-OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
-BYPRODUCTS ${sample_SRC}
-COMMAND Shiboken6::shiboken6 --project-file=${CMAKE_CURRENT_BINARY_DIR}/sample-binding.txt ${GENERATOR_EXTRA_FLAGS}
-DEPENDS ${sample_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
-WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-COMMENT "Running generator for 'sample' test binding..."
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${sample_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --project-file=${CMAKE_CURRENT_BINARY_DIR}/sample-binding.txt
+ ${GENERATOR_EXTRA_FLAGS}
+ DEPENDS ${sample_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for 'sample' test binding..."
)
add_library(sample MODULE ${sample_SRC})
diff --git a/sources/shiboken6/tests/samplebinding/__del___test.py b/sources/shiboken6/tests/samplebinding/__del___test.py
index 2d38b24d7..456886614 100644
--- a/sources/shiboken6/tests/samplebinding/__del___test.py
+++ b/sources/shiboken6/tests/samplebinding/__del___test.py
@@ -16,11 +16,13 @@ import sample
delCalled = False
+
class MyObject(sample.ObjectType):
def __del__(self):
global delCalled
delCalled = True
+
class TestDel(unittest.TestCase):
def testIt(self):
a = MyObject()
@@ -29,6 +31,6 @@ class TestDel(unittest.TestCase):
gc.collect()
self.assertTrue(delCalled)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/abstract_test.py b/sources/shiboken6/tests/samplebinding/abstract_test.py
index 252541af1..89e87be1d 100644
--- a/sources/shiboken6/tests/samplebinding/abstract_test.py
+++ b/sources/shiboken6/tests/samplebinding/abstract_test.py
@@ -15,10 +15,12 @@ init_paths()
from sample import Abstract
+
class Incomplete(Abstract):
def __init__(self):
Abstract.__init__(self)
+
class Concrete(Abstract):
def __init__(self):
Abstract.__init__(self)
@@ -60,12 +62,7 @@ class AbstractTest(unittest.TestCase):
# Python and calling it from C++ is undefined until it's decided how to
# cast the Python data types to void pointers
c = Concrete()
- self.assertEqual(c.pureVirtualReturningVoidPtr(),42)
-
- def testReimplementedVirtualMethodCall(self):
- '''Test if instanciation of an abstract class raises the correct exception.'''
- i = Concrete()
- self.assertRaises(NotImplementedError, i.callPureVirtual)
+ self.assertEqual(c.pureVirtualReturningVoidPtr(), 42)
def testReimplementedVirtualMethodCall(self):
'''Test if a Python override of a virtual method is correctly called from C++.'''
@@ -85,6 +82,6 @@ class AbstractTest(unittest.TestCase):
c.callVirtualGettingEnum(Abstract.Short)
self.assertTrue(c.virtual_getting_enum)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/addedfunction_test.py b/sources/shiboken6/tests/samplebinding/addedfunction_test.py
index 879bba7f2..0b5680143 100644
--- a/sources/shiboken6/tests/samplebinding/addedfunction_test.py
+++ b/sources/shiboken6/tests/samplebinding/addedfunction_test.py
@@ -14,6 +14,7 @@ from shiboken_paths import init_paths
init_paths()
from sample import SampleNamespace, ObjectType, Point
+
class TestAddedFunctionsWithSimilarTypes(unittest.TestCase):
'''Adds new signatures very similar to already existing ones.'''
@@ -38,5 +39,6 @@ class TestAddedFunctionsWithSimilarTypes(unittest.TestCase):
control = len(obj.objectName())
self.assertEqual(SampleNamespace.passReferenceToObjectType(obj), control)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/addedfunction_with_container_args_test.py b/sources/shiboken6/tests/samplebinding/addedfunction_with_container_args_test.py
index 3a570ccfd..2a739033b 100644
--- a/sources/shiboken6/tests/samplebinding/addedfunction_with_container_args_test.py
+++ b/sources/shiboken6/tests/samplebinding/addedfunction_with_container_args_test.py
@@ -14,18 +14,20 @@ from shiboken_paths import init_paths
init_paths()
from sample import sum2d, sumproduct
+
class TestAddedFunctionsWithContainerArgs(unittest.TestCase):
'''Tests added functions with nested and multi-argument container types.'''
def testNestedContainerType(self):
'''Test added function with single-argument containers.'''
- values = [[1,2],[3,4,5],[6]]
+ values = [[1, 2], [3, 4, 5], [6]]
self.assertEqual(sum2d(values), 21)
def testMultiArgContainerType(self):
'''Test added function with a two-argument container.'''
- values = [(1,2),(3,4),(5,6)]
+ values = [(1, 2), (3, 4), (5, 6)]
self.assertEqual(sumproduct(values), 44)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/argumentmodifications_test.py b/sources/shiboken6/tests/samplebinding/argumentmodifications_test.py
index 8158f89d2..b0ca56a6d 100644
--- a/sources/shiboken6/tests/samplebinding/argumentmodifications_test.py
+++ b/sources/shiboken6/tests/samplebinding/argumentmodifications_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import Modifications, Point
+
class ArgumentModificationsTest(unittest.TestCase):
'''Test cases for method arguments modifications performed as described on typesystem.'''
@@ -40,7 +41,8 @@ class ArgumentModificationsTest(unittest.TestCase):
def testArgRemoval1(self):
'''Tests argument removal modifications on Modifications.argRemoval1.'''
- # void [-> PyObject*] argRemoval1(int, bool, Point = Point(1, 2) [removed], Point = Point(3, 4) [removed], int = 333)
+ # void [-> PyObject*] argRemoval1(int, bool, Point = Point(1, 2) [removed],
+ # Point = Point(3, 4) [removed], int = 333)
# code-injection: returns tuple with received parameters plus removed ones
a0, a1, a2 = 1, True, 2
self.assertEqual(self.mods.argRemoval1(a0, a1), (a0, a1, Point(1, 2), Point(3, 4), 333))
@@ -51,7 +53,8 @@ class ArgumentModificationsTest(unittest.TestCase):
def testArgRemoval2(self):
'''Tests argument removal modifications on Modifications.argRemoval2.'''
- # void [-> PyObject*] argRemoval2(int, bool, Point = Point(1, 2) [removed], Point = Point(3, 4) [removed], int = 333)
+ # void [-> PyObject*] argRemoval2(int, bool, Point = Point(1, 2)
+ # [removed], Point = Point(3, 4) [removed], int = 333)
# code-injection: returns tuple with received parameters plus removed ones
a0, a1, a2 = 1, True, 2
self.assertEqual(self.mods.argRemoval2(a0, a1), (a0, a1, Point(1, 2), Point(3, 4), 333))
@@ -59,7 +62,8 @@ class ArgumentModificationsTest(unittest.TestCase):
def testArgRemoval3(self):
'''Tests argument removal modifications on Modifications.argRemoval3.'''
- # void [-> PyObject*] argRemoval3(int, Point = Point(1, 2) [removed], bool = true, Point = Point(3, 4) [removed], int = 333)
+ # void [-> PyObject*] argRemoval3(int, Point = Point(1, 2) [removed],
+ # bool = true, Point = Point(3, 4) [removed], int = 333)
# code-injection: returns tuple with received parameters plus removed ones
a0, a1, a2 = 1, True, 2
self.assertEqual(self.mods.argRemoval3(a0), (a0, Point(1, 2), True, Point(3, 4), 333))
@@ -68,7 +72,8 @@ class ArgumentModificationsTest(unittest.TestCase):
def testArgRemoval4(self):
'''Tests argument removal modifications on Modifications.argRemoval4.'''
- # void [-> PyObject*] argRemoval4(int, Point [removed, new val = Point(6, 9)], bool, Point = Point(3, 4) [removed], int = 333)
+ # void [-> PyObject*] argRemoval4(int, Point [removed, new val = Point(6, 9)], bool,
+ # Point = Point(3, 4) [removed], int = 333)
# code-injection: returns tuple with received parameters plus removed ones
a0, a1, a2 = 1, True, 2
self.assertRaises(TypeError, self.mods.argRemoval4, a0)
@@ -88,6 +93,6 @@ class ArgumentModificationsTest(unittest.TestCase):
# code-injection: returns tuple with received parameters plus removed ones
self.assertEqual(self.mods.argRemoval5(a0, a1, a2), (200, a0, a1, a2))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/array_numpy_test.py b/sources/shiboken6/tests/samplebinding/array_numpy_test.py
index ba9194122..0d73bca1c 100644
--- a/sources/shiboken6/tests/samplebinding/array_numpy_test.py
+++ b/sources/shiboken6/tests/samplebinding/array_numpy_test.py
@@ -22,24 +22,26 @@ try:
except ImportError:
pass
+
class ArrayTester(unittest.TestCase):
'''Test case for NumPy arrays.'''
def testIntArray(self):
- intList = numpy.array([1, 2, 3, 4], dtype = 'int32')
+ intList = numpy.array([1, 2, 3, 4], dtype='int32')
self.assertEqual(sample.sumIntArray(intList), 10)
def testDoubleArray(self):
- doubleList = numpy.array([1, 2, 3, 4], dtype = 'double')
+ doubleList = numpy.array([1, 2, 3, 4], dtype='double')
self.assertEqual(sample.sumDoubleArray(doubleList), 10)
def testIntMatrix(self):
- intMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'int32')
+ intMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype='int32')
self.assertEqual(sample.sumIntMatrix(intMatrix), 21)
def testDoubleMatrix(self):
- doubleMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'double')
+ doubleMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype='double')
self.assertEqual(sample.sumDoubleMatrix(doubleMatrix), 21)
+
if __name__ == '__main__' and hasNumPy:
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/array_sequence_test.py b/sources/shiboken6/tests/samplebinding/array_sequence_test.py
index cb5cbc49d..ad65d58db 100644
--- a/sources/shiboken6/tests/samplebinding/array_sequence_test.py
+++ b/sources/shiboken6/tests/samplebinding/array_sequence_test.py
@@ -14,6 +14,7 @@ from shiboken_paths import init_paths
init_paths()
import sample
+
class ArrayTester(unittest.TestCase):
'''Test case for arrays.'''
@@ -30,5 +31,6 @@ class ArrayTester(unittest.TestCase):
doubleList = [1.2, 2.3, 3.4, 4.5]
self.assertEqual(sample.sumDoubleArray(doubleList), 11.4)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/bug_554_test.py b/sources/shiboken6/tests/samplebinding/bug_554_test.py
index 6c4df6399..a7e7a7210 100644
--- a/sources/shiboken6/tests/samplebinding/bug_554_test.py
+++ b/sources/shiboken6/tests/samplebinding/bug_554_test.py
@@ -11,15 +11,15 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectType
+
class Bug554:
def crash(self):
class Crasher(ObjectType):
pass
+
if __name__ == '__main__':
bug = Bug554()
bug.crash()
-
-
diff --git a/sources/shiboken6/tests/samplebinding/bug_704_test.py b/sources/shiboken6/tests/samplebinding/bug_704_test.py
index 6de8fa3ea..c470fe723 100644
--- a/sources/shiboken6/tests/samplebinding/bug_704_test.py
+++ b/sources/shiboken6/tests/samplebinding/bug_704_test.py
@@ -25,13 +25,12 @@ def defineNewStyle():
class ObjectTypeTest(unittest.TestCase):
- '''Test cases to avoid declaring Shiboken classes with multiple inheritance from old style classes.'''
+ '''Test cases to avoid declaring Shiboken classes with multiple inheritance
+ from old style classes.'''
def testObjectTypeNewStype(self):
defineNewStyle()
-
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/bytearray_test.py b/sources/shiboken6/tests/samplebinding/bytearray_test.py
index e7c421b96..e51a899fa 100644
--- a/sources/shiboken6/tests/samplebinding/bytearray_test.py
+++ b/sources/shiboken6/tests/samplebinding/bytearray_test.py
@@ -34,7 +34,7 @@ class ByteArrayConcatenationOperatorTest(unittest.TestCase):
def testConcatPythonStringAndByteArray(self):
# Test concatenation of a Python string with a ByteArray, in this order.
- concat_python_string_add_qbytearray_worked = True
+ concat_python_string_add_qbytearray_worked = True # noqa: F841
ba = ByteArray('foo')
result = 'bar\x00' + ba
self.assertEqual(type(result), ByteArray)
@@ -80,14 +80,14 @@ class ByteArrayOperatorAt(unittest.TestCase):
# ByteArray[x] where x is a valid index (reverse order).
string = 'abcdefgh'
obj = ByteArray(string)
- for i in range(len(string)-1, 0, -1):
+ for i in range(len(string) - 1, 0, -1):
self.assertEqual(obj[i], bytes(string[i], "UTF8"))
def testOutOfRange(self):
# ByteArray[x] where x is out of index.
string = '1234567'
obj = ByteArray(string)
- self.assertRaises(IndexError, lambda :obj[len(string)])
+ self.assertRaises(IndexError, lambda: obj[len(string)])
def testNullStrings(self):
ba = ByteArray('\x00')
diff --git a/sources/shiboken6/tests/samplebinding/child_return_test.py b/sources/shiboken6/tests/samplebinding/child_return_test.py
index 97525bcb8..f0ac70626 100644
--- a/sources/shiboken6/tests/samplebinding/child_return_test.py
+++ b/sources/shiboken6/tests/samplebinding/child_return_test.py
@@ -14,7 +14,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectType
+
class ReturnOfChildTest(unittest.TestCase):
'''The BlackBox class has cases of ownership transference between C++ and Python.'''
@@ -37,6 +38,6 @@ class ReturnOfChildTest(unittest.TestCase):
gc.collect()
self.assertRaises(RuntimeError, child.objectName)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/class_fields_test.py b/sources/shiboken6/tests/samplebinding/class_fields_test.py
index 9da25e137..1eeb3d446 100644
--- a/sources/shiboken6/tests/samplebinding/class_fields_test.py
+++ b/sources/shiboken6/tests/samplebinding/class_fields_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Derived, Point, ObjectType
+
class TestAccessingCppFields(unittest.TestCase):
'''Simple test case for accessing the exposed C++ class fields.'''
@@ -36,7 +37,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertEqual(d.primitiveField, int(value))
# attribution with invalid type
- self.assertRaises(TypeError, lambda : setattr(d, 'primitiveField', None))
+ self.assertRaises(TypeError, lambda: setattr(d, 'primitiveField', None))
def testAccessingRenamedFields(self):
'''Reads and writes a renamed field.'''
@@ -72,7 +73,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertNotEqual(d.userPrimitiveField, old_value)
# attribution with invalid type
- self.assertRaises(TypeError, lambda : setattr(d, 'userPrimitiveField', None))
+ self.assertRaises(TypeError, lambda: setattr(d, 'userPrimitiveField', None))
def testAccessingValueTypeField(self):
'''Reads and writes a value type (in this case a 'Point') field.'''
@@ -80,7 +81,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertEqual(type(d.valueTypeField), Point)
# attribution
- old_value = d.valueTypeField
+ old_value = d.valueTypeField # noqa: F841
new_value = Point(-10, 537)
d.valueTypeField = new_value
self.assertEqual(d.valueTypeField, new_value)
@@ -92,7 +93,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertEqual(d.valueTypeField.y(), 20)
# attribution with invalid type
- self.assertRaises(TypeError, lambda : setattr(d, 'valueTypeField', 123))
+ self.assertRaises(TypeError, lambda: setattr(d, 'valueTypeField', 123))
def testAccessingObjectTypeField(self):
'''Reads and writes a object type (in this case an 'ObjectType') field.'''
@@ -111,7 +112,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertEqual(d.objectTypeField, value)
# attribution with invalid type
- self.assertRaises(TypeError, lambda : setattr(d, 'objectTypeField', 123))
+ self.assertRaises(TypeError, lambda: setattr(d, 'objectTypeField', 123))
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testRefCountingAccessingObjectTypeField(self):
@@ -155,7 +156,7 @@ class TestAccessingCppFields(unittest.TestCase):
# attribution
old_value = d.bitField
new_value = 1
- d.bitField= new_value
+ d.bitField = new_value
self.assertEqual(d.bitField, new_value)
self.assertNotEqual(d.bitField, old_value)
@@ -165,7 +166,7 @@ class TestAccessingCppFields(unittest.TestCase):
self.assertEqual(d.bitField, int(value))
# attribution with invalid type
- self.assertRaises(TypeError, lambda : setattr(d, 'bitField', None))
+ self.assertRaises(TypeError, lambda: setattr(d, 'bitField', None))
if __name__ == '__main__':
diff --git a/sources/shiboken6/tests/samplebinding/collector_test.py b/sources/shiboken6/tests/samplebinding/collector_test.py
index 376f91f1c..4caebc62a 100644
--- a/sources/shiboken6/tests/samplebinding/collector_test.py
+++ b/sources/shiboken6/tests/samplebinding/collector_test.py
@@ -33,6 +33,7 @@ class CollectorTest(unittest.TestCase):
self.assertEqual(collector.size(), 5)
self.assertEqual(collector.items(), [2, 3, 5, 7, 11])
+
class CollectorExternalOperator(unittest.TestCase):
'''Test cases for external operators of Collector'''
@@ -57,4 +58,3 @@ class CollectorObjectType(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/complex_test.py b/sources/shiboken6/tests/samplebinding/complex_test.py
index 6f0b23b2a..454aff100 100644
--- a/sources/shiboken6/tests/samplebinding/complex_test.py
+++ b/sources/shiboken6/tests/samplebinding/complex_test.py
@@ -16,6 +16,7 @@ init_paths()
import sample
from sample import Point
+
class ComplexTest(unittest.TestCase):
'''Test case for conversions between C++ Complex class to Python complex class'''
@@ -47,11 +48,14 @@ class ComplexTest(unittest.TestCase):
def testUsingTuples(self):
cpx1, cpx2 = (1.2, 3.4), (5.6, 7.8)
- self.assertEqual(sample.sumComplexPair((cpx1, cpx2)), sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
+ self.assertEqual(sample.sumComplexPair((cpx1, cpx2)),
+ sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
cpx1, cpx2 = (1, 3), (5, 7)
- self.assertEqual(sample.sumComplexPair((cpx1, cpx2)), sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
+ self.assertEqual(sample.sumComplexPair((cpx1, cpx2)),
+ sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
cpx1, cpx2 = (1.2, 3), (5.6, 7)
- self.assertEqual(sample.sumComplexPair((cpx1, cpx2)), sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
+ self.assertEqual(sample.sumComplexPair((cpx1, cpx2)),
+ sample.sumComplexPair((complex(*cpx1), complex(*cpx2))))
cpx1, cpx2 = (1, 2, 3), (4, 5, 7)
self.assertRaises(TypeError, sample.sumComplexPair, (cpx1, cpx2))
cpx1, cpx2 = ('1', '2'), ('4', '5')
@@ -60,4 +64,3 @@ class ComplexTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/conversion_operator_test.py b/sources/shiboken6/tests/samplebinding/conversion_operator_test.py
index f349ae82b..7e76245b1 100644
--- a/sources/shiboken6/tests/samplebinding/conversion_operator_test.py
+++ b/sources/shiboken6/tests/samplebinding/conversion_operator_test.py
@@ -15,11 +15,13 @@ init_paths()
from sample import Time, StrList
+
class ConversionOperatorTest(unittest.TestCase):
'''Test cases for implicit conversion generated by conversion operator.'''
def testConversionOperator(self):
- '''Time defined an conversion operator for Str, so passing a Time object to a method expecting a Str should work.'''
+ '''Time defined an conversion operator for Str, so passing a Time object
+ to a method expecting a Str should work.'''
t = Time(1, 2, 3)
t_str = t.toString()
sl = StrList()
@@ -30,6 +32,6 @@ class ConversionOperatorTest(unittest.TestCase):
self.assertEqual(len(sl), 1)
self.assertEqual(sl[0], t_str)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/copy_test.py b/sources/shiboken6/tests/samplebinding/copy_test.py
index 0a0533a41..db539d1b9 100644
--- a/sources/shiboken6/tests/samplebinding/copy_test.py
+++ b/sources/shiboken6/tests/samplebinding/copy_test.py
@@ -63,4 +63,3 @@ class PicklingTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ctorconvrule_test.py b/sources/shiboken6/tests/samplebinding/ctorconvrule_test.py
index 0ad21e35c..5e2695d72 100644
--- a/sources/shiboken6/tests/samplebinding/ctorconvrule_test.py
+++ b/sources/shiboken6/tests/samplebinding/ctorconvrule_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import CtorConvRule
+
class TestCtorConvRule(unittest.TestCase):
'''Simple test case for CtorConvRule'''
@@ -24,6 +25,6 @@ class TestCtorConvRule(unittest.TestCase):
obj = CtorConvRule(value)
self.assertEqual(obj.value(), value + 1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/cyclic_test.py b/sources/shiboken6/tests/samplebinding/cyclic_test.py
index b72e41b19..4e4ae2603 100644
--- a/sources/shiboken6/tests/samplebinding/cyclic_test.py
+++ b/sources/shiboken6/tests/samplebinding/cyclic_test.py
@@ -16,7 +16,6 @@ from sample import ObjectView
from sample import ObjectModel
-
class ObjTest(unittest.TestCase):
def test_cyclic_dependency_withParent(self):
@@ -37,7 +36,7 @@ class ObjTest(unittest.TestCase):
# turn off automatic garbage collection, to be able to trigger it
# at the 'right' time
gc.disable()
- alive = lambda :sum(isinstance(o, CyclicObject) for o in gc.get_objects() )
+ alive = lambda: sum(isinstance(o, CyclicObject) for o in gc.get_objects()) # noqa: E731
#
# first proof that the wizard is only destructed by the garbage
@@ -70,7 +69,7 @@ class ObjTest(unittest.TestCase):
# turn off automatic garbage collection, to be able to trigger it
# at the 'right' time
gc.disable()
- alive = lambda :sum(isinstance(o, CyclicObject) for o in gc.get_objects() )
+ alive = lambda: sum(isinstance(o, CyclicObject) for o in gc.get_objects()) # noqa: E731
#
# first proof that the wizard is only destructed by the garbage
@@ -85,6 +84,6 @@ class ObjTest(unittest.TestCase):
gc.collect()
self.assertFalse(alive())
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/date_test.py b/sources/shiboken6/tests/samplebinding/date_test.py
index a35861c8c..2b6efcf18 100644
--- a/sources/shiboken6/tests/samplebinding/date_test.py
+++ b/sources/shiboken6/tests/samplebinding/date_test.py
@@ -16,6 +16,7 @@ from datetime import date
from sample import SbkDate
+
class DateConversionTest(unittest.TestCase):
def testConstructorWithDateObject(self):
@@ -32,6 +33,6 @@ class DateConversionTest(unittest.TestCase):
self.assertTrue(cDate.month(), pyDate.month)
self.assertTrue(cDate.year(), pyDate.year)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/decisor_test.py b/sources/shiboken6/tests/samplebinding/decisor_test.py
index 6c7b4482d..0d39c5f96 100644
--- a/sources/shiboken6/tests/samplebinding/decisor_test.py
+++ b/sources/shiboken6/tests/samplebinding/decisor_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import SampleNamespace, Point, ObjectType, ObjectModel
+
class DecisorTest(unittest.TestCase):
'''Test cases for the method overload decisor.'''
@@ -37,11 +38,15 @@ class DecisorTest(unittest.TestCase):
'''Call methods overloads that receive parent and inheritor classes' instances.'''
objecttype = ObjectType()
objectmodel = ObjectModel()
- self.assertEqual(ObjectModel.receivesObjectTypeFamily(objecttype), ObjectModel.ObjectTypeCalled)
- self.assertNotEqual(ObjectModel.receivesObjectTypeFamily(objecttype), ObjectModel.ObjectModelCalled)
- self.assertEqual(ObjectModel.receivesObjectTypeFamily(objectmodel), ObjectModel.ObjectModelCalled)
- self.assertNotEqual(ObjectModel.receivesObjectTypeFamily(objectmodel), ObjectModel.ObjectTypeCalled)
+ self.assertEqual(ObjectModel.receivesObjectTypeFamily(objecttype),
+ ObjectModel.ObjectTypeCalled)
+ self.assertNotEqual(ObjectModel.receivesObjectTypeFamily(objecttype),
+ ObjectModel.ObjectModelCalled)
+ self.assertEqual(ObjectModel.receivesObjectTypeFamily(objectmodel),
+ ObjectModel.ObjectModelCalled)
+ self.assertNotEqual(ObjectModel.receivesObjectTypeFamily(objectmodel),
+ ObjectModel.ObjectTypeCalled)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/delete_test.py b/sources/shiboken6/tests/samplebinding/delete_test.py
index 5a4ee090e..57a792ae2 100644
--- a/sources/shiboken6/tests/samplebinding/delete_test.py
+++ b/sources/shiboken6/tests/samplebinding/delete_test.py
@@ -14,15 +14,15 @@ init_paths()
import sample
from shiboken6 import Shiboken
+
class DeleteTest(unittest.TestCase):
def testNonCppWrapperClassDelete(self):
- """Would segfault when shiboken.delete called on obj not created from
- Python """
+ """Would segfault when shiboken.delete called on obj not created from Python."""
obj = sample.ObjectType()
child = obj.createChild(None)
Shiboken.delete(child)
assert not Shiboken.isValid(child)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/deprecated_test.py b/sources/shiboken6/tests/samplebinding/deprecated_test.py
index 95b07f838..c371df94f 100644
--- a/sources/shiboken6/tests/samplebinding/deprecated_test.py
+++ b/sources/shiboken6/tests/samplebinding/deprecated_test.py
@@ -14,11 +14,13 @@ init_paths()
from sample import ObjectType
+
class TestDeprecatedCall(unittest.TestCase):
def testCallWithError(self):
o = ObjectType()
warnings.simplefilter('error')
self.assertRaises(DeprecationWarning, o.deprecatedFunction)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/derived_test.py b/sources/shiboken6/tests/samplebinding/derived_test.py
index 2d5eb4293..346f29136 100644
--- a/sources/shiboken6/tests/samplebinding/derived_test.py
+++ b/sources/shiboken6/tests/samplebinding/derived_test.py
@@ -16,6 +16,7 @@ init_paths()
import sample
from sample import Abstract, Derived, DerivedUsingCt, OverloadedFuncEnum
+
class Deviant(Derived):
def __init__(self):
Derived.__init__(self)
@@ -31,6 +32,16 @@ class Deviant(Derived):
def className(self):
return 'Deviant'
+
+class ImplementVirtualWithOutParameter(Derived):
+ def __init__(self, value):
+ super().__init__()
+ self._value = value
+
+ def virtualWithOutParameter(self):
+ return self._value
+
+
class DerivedTest(unittest.TestCase):
'''Test case for Derived class'''
@@ -40,24 +51,6 @@ class DerivedTest(unittest.TestCase):
'id_', 'pureVirtual', 'unpureVirtual'])
self.assertTrue(inherited_methods.issubset(dir(Derived)))
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testOverloadedMethodCall(self):
- '''Test if the correct overloaded method is being called.'''
- derived = Derived()
-
- result = derived.overloaded(1, 2)
- self.assertEqual(type(result), OverloadedFuncEnum)
- self.assertEqual(result, sample.OverloadedFunc_ii)
-
- result = derived.overloaded(3)
- self.assertEqual(type(result), OverloadedFuncEnum)
- self.assertEqual(result, sample.OverloadedFunc_ii)
-
- result = derived.overloaded(4.4)
- self.assertEqual(type(result), OverloadedFuncEnum)
- self.assertEqual(result, sample.OverloadedFunc_d)
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
def testOtherOverloadedMethodCall(self):
'''Another test to check overloaded method calling, just to double check.'''
derived = Derived()
@@ -70,27 +63,28 @@ class DerivedTest(unittest.TestCase):
self.assertEqual(type(result), Derived.OtherOverloadedFuncEnum)
self.assertEqual(result, Derived.OtherOverloadedFunc_id)
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
def testOverloadedMethodCallWithDifferentNumericTypes(self):
'''Test if the correct overloaded method accepts a different numeric type as argument.'''
derived = Derived()
result = derived.overloaded(1.1, 2.2)
self.assertEqual(type(result), OverloadedFuncEnum)
- self.assertEqual(result, sample.OverloadedFunc_ii)
def testOverloadedMethodCallWithWrongNumberOfArguments(self):
- '''Test if a call to an overloaded method with the wrong number of arguments raises an exception.'''
+ '''Test if a call to an overloaded method with the wrong number of arguments
+ raises an exception.'''
derived = Derived()
self.assertRaises(TypeError, derived.otherOverloaded, 1, 2, True)
def testReimplementedPureVirtualMethodCall(self):
- '''Test if a Python override of a implemented pure virtual method is correctly called from C++.'''
+ '''Test if a Python override of a implemented pure virtual method is
+ correctly called from C++.'''
d = Deviant()
d.callPureVirtual()
self.assertTrue(d.pure_virtual_called)
def testReimplementedVirtualMethodCall(self):
- '''Test if a Python override of a reimplemented virtual method is correctly called from C++.'''
+ '''Test if a Python override of a reimplemented virtual method is
+ correctly called from C++.'''
d = Deviant()
d.callUnpureVirtual()
self.assertTrue(d.unpure_virtual_called)
@@ -102,7 +96,8 @@ class DerivedTest(unittest.TestCase):
self.assertEqual(d.getClassName(), 'Derived')
def testReimplementedVirtualMethodCallReturningString(self):
- '''Test if a Python override of a reimplemented virtual method is correctly called from C++.'''
+ '''Test if a Python override of a reimplemented virtual method is
+ correctly called from C++.'''
d = Deviant()
self.assertEqual(d.className(), 'Deviant')
self.assertEqual(d.getClassName(), 'Deviant')
@@ -126,7 +121,8 @@ class DerivedTest(unittest.TestCase):
self.assertEqual(Abstract.getObjectId(d), objId)
def testObjectCreationWithParentType(self):
- '''Derived class creates an instance of itself in C++ and returns it as a pointer to its ancestor Abstract.'''
+ '''Derived class creates an instance of itself in C++ and returns it as
+ a pointer to its ancestor Abstract.'''
obj = Derived.createObject()
self.assertEqual(type(obj), Derived)
@@ -135,7 +131,13 @@ class DerivedTest(unittest.TestCase):
obj = DerivedUsingCt(42)
self.assertEqual(obj.value(), 42)
+ def testVirtualWithOutParameter(self):
+ d = Derived()
+ self.assertEqual(d.callVirtualWithOutParameter(), 42)
+
+ d = ImplementVirtualWithOutParameter(1)
+ self.assertEqual(d.callVirtualWithOutParameter(), 1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/duck_punching_test.py b/sources/shiboken6/tests/samplebinding/duck_punching_test.py
index e1d89e2c0..aa21a0f7e 100644
--- a/sources/shiboken6/tests/samplebinding/duck_punching_test.py
+++ b/sources/shiboken6/tests/samplebinding/duck_punching_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import VirtualMethods, SimpleFile, Point
+
def MethodTypeCompat(func, instance):
return types.MethodType(func, instance)
@@ -24,10 +25,12 @@ class Duck(VirtualMethods):
def __init__(self):
VirtualMethods.__init__(self)
+
class Monkey(SimpleFile):
def __init__(self, filename):
SimpleFile.__init__(self, filename)
+
class DuckPunchingTest(unittest.TestCase):
'''Test case for duck punching (aka "monkey patching").'''
@@ -56,7 +59,8 @@ class DuckPunchingTest(unittest.TestCase):
result2 = vm.virtualMethod0(pt, val, cpx, b)
self.assertEqual(result1, result2)
- self.assertEqual(result1, VirtualMethods.virtualMethod0(vm, pt, val, cpx, b) * self.multiplier)
+ self.assertEqual(result1,
+ VirtualMethods.virtualMethod0(vm, pt, val, cpx, b) * self.multiplier)
# This is done to decrease the refcount of the vm object
# allowing the object wrapper to be deleted before the
@@ -66,7 +70,8 @@ class DuckPunchingTest(unittest.TestCase):
vm.virtualMethod0 = None
def testMonkeyPatchOnVirtualMethodWithInheritance(self):
- '''Injects new 'virtualMethod0' on an object that inherits from VirtualMethods and makes C++ call it.'''
+ '''Injects new 'virtualMethod0' on an object that inherits from
+ VirtualMethods and makes C++ call it.'''
duck = Duck()
pt, val, cpx, b = Point(1.1, 2.2), 4, complex(3.3, 4.4), True
@@ -85,7 +90,8 @@ class DuckPunchingTest(unittest.TestCase):
result2 = duck.virtualMethod0(pt, val, cpx, b)
self.assertEqual(result1, result2)
- self.assertEqual(result1, VirtualMethods.virtualMethod0(duck, pt, val, cpx, b) * self.multiplier)
+ self.assertEqual(result1,
+ VirtualMethods.virtualMethod0(duck, pt, val, cpx, b) * self.multiplier)
duck.virtualMethod0 = None
@@ -150,4 +156,3 @@ class DuckPunchingTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/echo_test.py b/sources/shiboken6/tests/samplebinding/echo_test.py
index 567d1452a..f1859260e 100644
--- a/sources/shiboken6/tests/samplebinding/echo_test.py
+++ b/sources/shiboken6/tests/samplebinding/echo_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Echo
+
class TestEcho(unittest.TestCase):
'''Simple test case for Echo.echo'''
@@ -26,7 +27,8 @@ class TestEcho(unittest.TestCase):
def testCallOperator(self):
e = Echo()
- self.assertEqual(e("Hello", 3), "Hello3");
+ self.assertEqual(e("Hello", 3), "Hello3")
+
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/enum_test.py b/sources/shiboken6/tests/samplebinding/enum_test.py
index 9284257f0..276b8d894 100644
--- a/sources/shiboken6/tests/samplebinding/enum_test.py
+++ b/sources/shiboken6/tests/samplebinding/enum_test.py
@@ -13,35 +13,27 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-import shiboken6
# This is needed after the introduction of BUILD_DIR.
import sample
from sample import SampleNamespace, ObjectType, Event
+
def createTempFile():
import tempfile
return tempfile.SpooledTemporaryFile(mode='rw')
+
class EnumTest(unittest.TestCase):
'''Test case for Python representation of C++ enums.'''
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
- def testEnumRepr(self):
- enum = SampleNamespace.Option(1)
- self.assertEqual(eval(repr(enum)), enum)
-
- enum = SampleNamespace.Option(999)
- self.assertEqual(eval(repr(enum)), enum)
-
def testHashability(self):
self.assertEqual(hash(SampleNamespace.TwoIn), hash(SampleNamespace.TwoOut))
self.assertNotEqual(hash(SampleNamespace.TwoIn), hash(SampleNamespace.OneIn))
def testEnumValuesInsideEnum(self):
'''Enum values should be accessible inside the enum as well as outside.'''
- for value_name in (SampleNamespace.Option.__members__ if sys.pyside63_option_python_enum
- else SampleNamespace.Option.values):
+ for value_name in SampleNamespace.Option.__members__:
enum_item1 = getattr(SampleNamespace.Option, value_name)
enum_item2 = getattr(SampleNamespace, value_name)
self.assertEqual(enum_item1, enum_item2)
@@ -54,13 +46,11 @@ class EnumTest(unittest.TestCase):
'''Tries to build the proper enum using an integer.'''
SampleNamespace.getNumber(SampleNamespace.Option(1))
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
def testBuildingEnumWithDefaultValue(self):
'''Enum constructor with default value'''
enum = SampleNamespace.Option()
self.assertEqual(enum, SampleNamespace.None_)
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
def testEnumConversionToAndFromPython(self):
'''Conversion of enum objects from Python to C++ back again.'''
enumout = SampleNamespace.enumInEnumOut(SampleNamespace.TwoIn)
@@ -69,7 +59,7 @@ class EnumTest(unittest.TestCase):
def testEnumConstructorWithTooManyParameters(self):
'''Calling the constructor of non-extensible enum with the wrong number of parameters.'''
- self.assertRaises(TypeError, SampleNamespace.InValue, 13, 14)
+ self.assertRaises((TypeError, ValueError), SampleNamespace.InValue, 13, 14)
def testEnumConstructorWithNonNumberParameter(self):
'''Calling the constructor of non-extensible enum with a string.'''
@@ -77,8 +67,10 @@ class EnumTest(unittest.TestCase):
def testEnumItemAsDefaultValueToIntArgument(self):
'''Calls function with an enum item as default value to an int argument.'''
- self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(), SampleNamespace.ZeroIn)
- self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(SampleNamespace.ZeroOut), SampleNamespace.ZeroOut)
+ self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(),
+ SampleNamespace.ZeroIn)
+ self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(SampleNamespace.ZeroOut), # noqa E:501
+ SampleNamespace.ZeroOut)
self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(123), 123)
def testAnonymousGlobalEnums(self):
@@ -103,55 +95,25 @@ class EnumTest(unittest.TestCase):
self.assertEqual(event.eventType(), Event.BASIC_EVENT)
event.setEventTypeByConstRef(Event.SOME_EVENT)
self.assertEqual(event.eventType(), Event.SOME_EVENT)
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
- def testEnumTpPrintImplementation(self):
- '''Without SbkEnum.tp_print 'print' returns the enum represented as an int.'''
- tmpfile = createTempFile()
- print(Event.ANY_EVENT, file=tmpfile)
- tmpfile.seek(0)
- text = tmpfile.read().strip()
- tmpfile.close()
- self.assertEqual(text, str(Event.ANY_EVENT))
- self.assertEqual(text, repr(Event.ANY_EVENT))
+ event.setEventTypeByConstPtr(Event.BASIC_EVENT)
+ self.assertEqual(event.eventType(), Event.BASIC_EVENT)
def testEnumArgumentWithDefaultValue(self):
'''Option enumArgumentWithDefaultValue(Option opt = UnixTime);'''
self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(), SampleNamespace.UnixTime)
- self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(SampleNamespace.RandomNumber), SampleNamespace.RandomNumber)
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
- def testSignature(self):
- enum = SampleNamespace.Option(1)
- types = type(enum).mro()
- klass = types[0]
- base = types[1]
- # The class has an empty signature.
-
- self.assertEqual(klass.__signature__, None)
- # The base class must be Enum
- self.assertNotEqual(base.__signature__, None)
- # It contains an int annotation.
- param = base.__signature__.parameters["itemValue"]
- self.assertEqual(param.annotation, int)
+ self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(SampleNamespace.RandomNumber), # noqa E:501
+ SampleNamespace.RandomNumber)
class MyEvent(Event):
def __init__(self):
- Event.__init__(self, Event.EventType(3 if sys.pyside63_option_python_enum else 999))
+ Event.__init__(self, Event.EventType(3))
class OutOfBoundsTest(unittest.TestCase):
def testValue(self):
e = MyEvent()
- self.assertEqual(repr(e.eventType()), "<EventType.ANY_EVENT: 3>"
- if sys.pyside63_option_python_enum else 'sample.Event.EventType(999)')
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "test not suitable for Python enum")
- def testNoneName(self):
- e = MyEvent()
- t = e.eventType()
- self.assertEqual(t.name, None)
+ self.assertEqual(repr(e.eventType()), "<EventType.ANY_EVENT: 3>")
class EnumOverloadTest(unittest.TestCase):
@@ -174,4 +136,3 @@ class EnumOperators(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/enumfromremovednamespace_test.py b/sources/shiboken6/tests/samplebinding/enumfromremovednamespace_test.py
index f70621c59..42ae23961 100644
--- a/sources/shiboken6/tests/samplebinding/enumfromremovednamespace_test.py
+++ b/sources/shiboken6/tests/samplebinding/enumfromremovednamespace_test.py
@@ -14,23 +14,11 @@ init_paths()
import sample
from shiboken_test_helper import objectFullname
-from shiboken6 import Shiboken
-_init_pyside_extension() # trigger bootstrap
-
from shibokensupport.signature import get_signature
class TestEnumFromRemovedNamespace(unittest.TestCase):
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testEnumPromotedToGlobal(self):
- sample.RemovedNamespace1_Enum
- self.assertEqual(sample.RemovedNamespace1_Enum_Value0, 0)
- self.assertEqual(sample.RemovedNamespace1_Enum_Value1, 1)
- sample.RemovedNamespace1_AnonymousEnum_Value0
- sample.RemovedNamespace2_Enum
- sample.RemovedNamespace2_Enum_Value0
-
def testNames(self):
# Test if invisible namespace does not appear on type name
self.assertEqual(objectFullname(sample.RemovedNamespace1_Enum),
@@ -56,9 +44,8 @@ class TestEnumFromRemovedNamespace(unittest.TestCase):
sample.UnremovedNamespace.RemovedNamespace3_AnonymousEnum_Value0
def testNestedFunctionFromRemovedNamespace(self):
- self.assertEqual(sample.UnremovedNamespace.nestedMathSum(1, 2), 3)
+ self.assertEqual(sample.UnremovedNamespace.nestedMathSum(1, 2), 3)
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/event_loop_call_virtual_test.py b/sources/shiboken6/tests/samplebinding/event_loop_call_virtual_test.py
index e61656400..8e13d5d46 100644
--- a/sources/shiboken6/tests/samplebinding/event_loop_call_virtual_test.py
+++ b/sources/shiboken6/tests/samplebinding/event_loop_call_virtual_test.py
@@ -6,14 +6,12 @@
import os
import sys
-import time
import unittest
from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from random import random
from sample import ObjectType, Event
@@ -41,7 +39,7 @@ class TestEventLoop(unittest.TestCase):
objs = [ObjectType(), NoOverride(), Override()]
evaluated = ObjectType.processEvent(objs,
- Event(Event.BASIC_EVENT))
+ Event(Event.BASIC_EVENT))
self.assertEqual(evaluated, 3)
self.assertTrue(objs[2].called)
diff --git a/sources/shiboken6/tests/samplebinding/event_loop_thread_test.py b/sources/shiboken6/tests/samplebinding/event_loop_thread_test.py
index 2cd1c8d0a..8b854fca6 100644
--- a/sources/shiboken6/tests/samplebinding/event_loop_thread_test.py
+++ b/sources/shiboken6/tests/samplebinding/event_loop_thread_test.py
@@ -64,7 +64,7 @@ class TestEventLoopWithThread(unittest.TestCase):
thread.start()
evaluated = ObjectType.processEvent(objs,
- Event(Event.BASIC_EVENT))
+ Event(Event.BASIC_EVENT))
thread.join()
diff --git a/sources/shiboken6/tests/samplebinding/exception_test.py b/sources/shiboken6/tests/samplebinding/exception_test.py
index d502609bf..d9e6b377f 100644
--- a/sources/shiboken6/tests/samplebinding/exception_test.py
+++ b/sources/shiboken6/tests/samplebinding/exception_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import ExceptionTest
+
class CppExceptionTest(unittest.TestCase):
def testVoid(self):
@@ -23,14 +24,14 @@ class CppExceptionTest(unittest.TestCase):
try:
et.voidThrowStdException(True)
- except:
+ except: # noqa: E722
exceptionCount += 1
et.voidThrowInt(False)
try:
et.voidThrowInt(True)
- except:
+ except: # noqa: E722
exceptionCount += 1
self.assertEqual(exceptionCount, 2)
@@ -39,21 +40,32 @@ class CppExceptionTest(unittest.TestCase):
exceptionCount = 0
et = ExceptionTest()
- result = et.intThrowStdException(False);
+ result = et.intThrowStdException(False)
try:
- result = et.intThrowStdException(True);
- except:
+ result = et.intThrowStdException(True)
+ except: # noqa: E722
exceptionCount += 1
- result = et.intThrowInt(False);
+ result = et.intThrowInt(False)
try:
- result = et.intThrowInt(True);
- except:
+ result = et.intThrowInt(True) # noqa: F841
+ except: # noqa: E722
exceptionCount += 1
self.assertEqual(exceptionCount, 2)
+ def testModifications(self):
+ """PYSIDE-1995, test whether exceptions are propagated
+ when return ownership modifications are generated."""
+ exceptionCount = 0
+ try:
+ et = ExceptionTest.create(True) # noqa: F841
+ except: # noqa: E722
+ exceptionCount += 1
+ self.assertEqual(exceptionCount, 1)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/filter_test.py b/sources/shiboken6/tests/samplebinding/filter_test.py
index 86c5fba2a..df805093f 100644
--- a/sources/shiboken6/tests/samplebinding/filter_test.py
+++ b/sources/shiboken6/tests/samplebinding/filter_test.py
@@ -12,6 +12,7 @@ init_paths()
from sample import Data, Intersection, Union
+
class TestFilters(unittest.TestCase):
def testAnd(self):
@@ -23,5 +24,6 @@ class TestFilters(unittest.TestCase):
self.assertEqual(type(inter), Intersection)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/global.h b/sources/shiboken6/tests/samplebinding/global.h
index f73fdd503..64806417a 100644
--- a/sources/shiboken6/tests/samplebinding/global.h
+++ b/sources/shiboken6/tests/samplebinding/global.h
@@ -56,6 +56,7 @@
#include "removednamespaces.h"
#include "sample.h"
#include "samplenamespace.h"
+#include "stdcomplex.h"
#include "simplefile.h"
#include "size.h"
#include "snakecasetest.h"
diff --git a/sources/shiboken6/tests/samplebinding/handleholder_test.py b/sources/shiboken6/tests/samplebinding/handleholder_test.py
index 273915719..af22328c5 100644
--- a/sources/shiboken6/tests/samplebinding/handleholder_test.py
+++ b/sources/shiboken6/tests/samplebinding/handleholder_test.py
@@ -17,6 +17,7 @@ init_paths()
from sample import HandleHolder
+
class HandleHolderTest(unittest.TestCase):
def testCreation(self):
holder = HandleHolder(HandleHolder.createHandle())
@@ -33,5 +34,6 @@ class HandleHolderTest(unittest.TestCase):
holder2 = HandleHolder(holder.handle2())
self.assertTrue(holder.compare2(holder2))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/hashabletype_test.py b/sources/shiboken6/tests/samplebinding/hashabletype_test.py
index 20d3d2edd..c41f5cc06 100644
--- a/sources/shiboken6/tests/samplebinding/hashabletype_test.py
+++ b/sources/shiboken6/tests/samplebinding/hashabletype_test.py
@@ -13,7 +13,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectType, Str
+
class HashableTest(unittest.TestCase):
@@ -29,6 +30,6 @@ class HashableTest(unittest.TestCase):
h[o] = 2
self.assertTrue(h.get(o), 2)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ignorederefop_test.py b/sources/shiboken6/tests/samplebinding/ignorederefop_test.py
index 89df035a3..feb78d045 100644
--- a/sources/shiboken6/tests/samplebinding/ignorederefop_test.py
+++ b/sources/shiboken6/tests/samplebinding/ignorederefop_test.py
@@ -9,12 +9,14 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Reference
+
class TestLackOfDereferenceOperators (unittest.TestCase):
def testIf(self):
r = Reference()
self.assertFalse(hasattr(r, "__mul__"))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/implicitconv_numerical_test.py b/sources/shiboken6/tests/samplebinding/implicitconv_numerical_test.py
index c5c7bc0d1..081666281 100644
--- a/sources/shiboken6/tests/samplebinding/implicitconv_numerical_test.py
+++ b/sources/shiboken6/tests/samplebinding/implicitconv_numerical_test.py
@@ -27,6 +27,7 @@ if is64bitArchitecture and sys.platform != 'win32':
cLongMin = -9223372036854775808
cLongMax = 9223372036854775807
+
class NumericTester(unittest.TestCase):
'''Helper class for numeric comparison testing'''
diff --git a/sources/shiboken6/tests/samplebinding/implicitconv_test.py b/sources/shiboken6/tests/samplebinding/implicitconv_test.py
index 96cad9c69..ebafe0c52 100644
--- a/sources/shiboken6/tests/samplebinding/implicitconv_test.py
+++ b/sources/shiboken6/tests/samplebinding/implicitconv_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import ImplicitConv, ObjectType
+
class ImplicitConvTest(unittest.TestCase):
'''Test case for implicit conversions'''
@@ -43,4 +44,3 @@ class ImplicitConvTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/inheritanceandscope_test.py b/sources/shiboken6/tests/samplebinding/inheritanceandscope_test.py
index 7ae676102..28d62486a 100644
--- a/sources/shiboken6/tests/samplebinding/inheritanceandscope_test.py
+++ b/sources/shiboken6/tests/samplebinding/inheritanceandscope_test.py
@@ -15,14 +15,16 @@ init_paths()
from sample import SampleNamespace
+
class ScopeAndInheritanceTest(unittest.TestCase):
'''Test cases for finding scope in cases involving inheritance.'''
def testMethodCorrectlyWrapper(self):
'''A method returning a type declared in the scope of the method's
class parent must be found and the method correctly exported.'''
- meth = getattr(SampleNamespace.DerivedFromNamespace, 'methodReturningTypeFromParentScope')
+ meth = getattr(SampleNamespace.DerivedFromNamespace, # noqa: F841
+ 'methodReturningTypeFromParentScope')
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/injectcode_test.py b/sources/shiboken6/tests/samplebinding/injectcode_test.py
index 90225a039..f673a7807 100644
--- a/sources/shiboken6/tests/samplebinding/injectcode_test.py
+++ b/sources/shiboken6/tests/samplebinding/injectcode_test.py
@@ -14,6 +14,7 @@ from shiboken_paths import init_paths
init_paths()
from sample import InjectCode
+
class MyInjectCode(InjectCode):
def __init__(self):
InjectCode.__init__(self)
@@ -22,10 +23,11 @@ class MyInjectCode(InjectCode):
def arrayMethod(self, values):
return self.multiplier * sum(values)
+
class InjectCodeTest(unittest.TestCase):
@unittest.skipIf(hasattr(sys, "pypy_version_info"),
- "PyPy type objects cannot be modified (yet) after creation")
+ "PyPy type objects cannot be modified (yet) after creation")
def testTypeNativeBeginning_TypeTargetBeginning(self):
ic = InjectCode()
self.assertEqual(str(ic), "Hi! I'm the inject code dummy class.")
@@ -71,22 +73,24 @@ class InjectCodeTest(unittest.TestCase):
self.assertEqual(result, sum(values))
def testCallReimplementedVirtualMethodWithArgumentRemovalAndArgumentTypeModification(self):
- '''Calls a reimplemented virtual method that had its first argument removed and the second modified.'''
+ '''Calls a reimplemented virtual method that had its first argument removed
+ and the second modified.'''
ic = MyInjectCode()
values = (1, 2, 3, 4, 5)
result = ic.callArrayMethod(values)
self.assertEqual(result, ic.multiplier * sum(values))
def testUsageOfTypeSystemCheckVariableOnPrimitiveType(self):
- '''When the sequence item is convertible to an integer -1 is returned, or -2 if its not convertible.'''
+ '''When the sequence item is convertible to an integer -1 is returned,
+ or -2 if its not convertible.'''
ic = InjectCode()
values = (1, 2, 3, 4, '5', 6.7)
result = ic.arrayMethod(values)
- fixedValues = [v for v in values if isinstance(v, int)]\
- + [-1 for v in values if isinstance(v, float)]\
- + [-2 for v in values if not isinstance(v, int) and not isinstance(v, float)]
- self.assertEqual(result, sum(fixedValues))
+ ints = [v for v in values if isinstance(v, int)]
+ floats = [-1 for v in values if isinstance(v, float)]
+ other = [-2 for v in values if not isinstance(v, int) and not isinstance(v, float)]
+ self.assertEqual(result, sum(ints + floats + other))
class IntArrayTest(unittest.TestCase):
@@ -110,5 +114,6 @@ class IntArrayTest(unittest.TestCase):
ic = InjectCode()
self.assertEqual(sum([1, 2]) + len([1, 2]), ic.sumArrayAndLength(args))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/innerclass_test.py b/sources/shiboken6/tests/samplebinding/innerclass_test.py
index f94c57750..721f33483 100644
--- a/sources/shiboken6/tests/samplebinding/innerclass_test.py
+++ b/sources/shiboken6/tests/samplebinding/innerclass_test.py
@@ -13,10 +13,11 @@ init_paths()
from sample import Derived
+
class TestInnerClass(unittest.TestCase):
def testInstaciate(self):
- d = Derived.SomeInnerClass()
+ d = Derived.SomeInnerClass() # noqa: F841
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/intlist_test.py b/sources/shiboken6/tests/samplebinding/intlist_test.py
index 41d2b659a..defa9ca71 100644
--- a/sources/shiboken6/tests/samplebinding/intlist_test.py
+++ b/sources/shiboken6/tests/samplebinding/intlist_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import IntList
+
class IntListTest(unittest.TestCase):
def testAutoFunctionsToBaseList(self):
@@ -74,5 +75,6 @@ class IntListTest(unittest.TestCase):
self.assertEqual(il[1], int(432.1))
self.assertRaises(TypeError, il.__setitem__, 2, '78')
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/intwrapper_test.py b/sources/shiboken6/tests/samplebinding/intwrapper_test.py
index 21cab6b35..d883adf47 100644
--- a/sources/shiboken6/tests/samplebinding/intwrapper_test.py
+++ b/sources/shiboken6/tests/samplebinding/intwrapper_test.py
@@ -16,8 +16,8 @@ from sample import IntWrapper
class IntWrapperTest(unittest.TestCase):
def testOperators(self):
- ten1 = IntWrapper(10)
- ten2 = IntWrapper(10)
+ ten1 = IntWrapper(10)
+ ten2 = IntWrapper(10)
twenty = IntWrapper(20)
self.assertTrue(ten1 == ten2)
self.assertTrue(ten1 != twenty)
diff --git a/sources/shiboken6/tests/samplebinding/invalid_virtual_return_test.py b/sources/shiboken6/tests/samplebinding/invalid_virtual_return_test.py
index e3d060430..bb35b2bb1 100644
--- a/sources/shiboken6/tests/samplebinding/invalid_virtual_return_test.py
+++ b/sources/shiboken6/tests/samplebinding/invalid_virtual_return_test.py
@@ -38,7 +38,7 @@ class ModelWrongReturnTest(unittest.TestCase):
def testWrongTypeReturn(self):
model = ListModelWrong()
view = ObjectView(model)
- self.assertRaises(RuntimeWarning, view.getRawModelData) # calls model.data()
+ self.assertRaises(RuntimeWarning, view.getRawModelData) # calls model.data()
if __name__ == '__main__':
diff --git a/sources/shiboken6/tests/samplebinding/keep_reference_test.py b/sources/shiboken6/tests/samplebinding/keep_reference_test.py
index 6cf416fc4..10591fec6 100644
--- a/sources/shiboken6/tests/samplebinding/keep_reference_test.py
+++ b/sources/shiboken6/tests/samplebinding/keep_reference_test.py
@@ -2,8 +2,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).'''
-
import os
import sys
import unittest
@@ -15,8 +13,10 @@ init_paths()
from sample import ObjectModel, ObjectView
+
class TestKeepReference(unittest.TestCase):
- '''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).'''
+ '''Test case for objects that keep references to other object without
+ owning them (e.g. model/view relationships).'''
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testReferenceCounting(self):
@@ -48,15 +48,16 @@ class TestKeepReference(unittest.TestCase):
self.assertEqual(sys.getrefcount(model), refcount1)
def testReferreedObjectSurvivalAfterContextEnd(self):
- '''Model-like object assigned to a view-like object must survive after get out of context.'''
+ '''Model-like object assigned to a view-like object must survive
+ after get out of context.'''
def createModelAndSetToView(view):
model = ObjectModel()
model.setObjectName('created model')
view.setModel(model)
view = ObjectView()
createModelAndSetToView(view)
- model = view.model()
+ model = view.model() # noqa: F841
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/list_test.py b/sources/shiboken6/tests/samplebinding/list_test.py
index 6eb975b9f..b668bfd90 100644
--- a/sources/shiboken6/tests/samplebinding/list_test.py
+++ b/sources/shiboken6/tests/samplebinding/list_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import ListUser, Point, PointF
+
class ExtendedListUser(ListUser):
def __init__(self):
ListUser.__init__(self)
@@ -24,6 +25,7 @@ class ExtendedListUser(ListUser):
self.create_list_called = True
return [2, 3, 5, 7, 13]
+
class ListConversionTest(unittest.TestCase):
'''Test case for std::list container conversions'''
@@ -69,7 +71,8 @@ class ListConversionTest(unittest.TestCase):
self.assertEqual(result, lst)
def testConversionInBothDirectionsWithSimilarContainer(self):
- '''Test converting a tuple, instead of the expected list, from Python to C++ and back again.'''
+ '''Test converting a tuple, instead of the expected list,
+ from Python to C++ and back again.'''
lu = ListUser()
lst = (3, 5, 7)
lu.setList(lst)
@@ -96,6 +99,6 @@ class ListConversionTest(unittest.TestCase):
self.assertEqual(ListUser.ListOfPointF, ListUser.listOfPoints([PointF()]))
self.assertEqual(ListUser.ListOfPoint, ListUser.listOfPoints([Point()]))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/lock_test.py b/sources/shiboken6/tests/samplebinding/lock_test.py
index 0657d41b9..acd47634a 100644
--- a/sources/shiboken6/tests/samplebinding/lock_test.py
+++ b/sources/shiboken6/tests/samplebinding/lock_test.py
@@ -63,7 +63,8 @@ class TestLockUnlock(unittest.TestCase):
self.assertTrue(result)
def testReimplementedVirtualBlocker(self):
- '''Same as the basic case but blocker method is a C++ virtual reimplemented in Python and called from C++.'''
+ '''Same as the basic case but blocker method is a C++ virtual reimplemented
+ in Python and called from C++.'''
mybucket = MyBucket()
unlocker = Unlocker(mybucket)
@@ -72,5 +73,6 @@ class TestLockUnlock(unittest.TestCase):
unlocker.join()
self.assertTrue(result)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/map_test.py b/sources/shiboken6/tests/samplebinding/map_test.py
index 5ffed5ede..fa99ad2e7 100644
--- a/sources/shiboken6/tests/samplebinding/map_test.py
+++ b/sources/shiboken6/tests/samplebinding/map_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import MapUser
+
class ExtendedMapUser(MapUser):
def __init__(self):
MapUser.__init__(self)
@@ -22,10 +23,11 @@ class ExtendedMapUser(MapUser):
def createMap(self):
self.create_map_called = True
- return {'two' : (complex(2.2, 2.2), 2),
- 'three' : (complex(3.3, 3.3), 3),
- 'five' : (complex(5.5, 5.5), 5),
- 'seven' : (complex(7.7, 7.7), 7)}
+ return {'two': (complex(2.2, 2.2), 2),
+ 'three': (complex(3.3, 3.3), 3),
+ 'five': (complex(5.5, 5.5), 5),
+ 'seven': (complex(7.7, 7.7), 7)}
+
class MapConversionTest(unittest.TestCase):
'''Test case for std::map container conversions'''
@@ -44,7 +46,7 @@ class MapConversionTest(unittest.TestCase):
def testConversionInBothDirections(self):
'''Test converting a map from Python to C++ and back again.'''
mu = MapUser()
- map_ = {'odds' : [2, 4, 6], 'evens' : [3, 5, 7], 'primes' : [3, 4, 6]}
+ map_ = {'odds': [2, 4, 6], 'evens': [3, 5, 7], 'primes': [3, 4, 6]}
mu.setMap(map_)
result = mu.getMap()
self.assertEqual(result, map_)
@@ -52,9 +54,10 @@ class MapConversionTest(unittest.TestCase):
def testConversionMapIntKeyValueTypeValue(self):
'''C++ signature: MapUser::passMapIntValueType(const std::map<int, const ByteArray>&)'''
mu = MapUser()
- map_ = {0 : 'string'}
+ map_ = {0: 'string'}
result = mu.passMapIntValueType(map_)
self.assertEqual(map_, result)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/metaclass_test.py b/sources/shiboken6/tests/samplebinding/metaclass_test.py
index 787bace70..4d7eeda96 100644
--- a/sources/shiboken6/tests/samplebinding/metaclass_test.py
+++ b/sources/shiboken6/tests/samplebinding/metaclass_test.py
@@ -10,32 +10,40 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Point
+
class MetaA(type):
pass
+
class A(object):
__metaclass__ = MetaA
+
MetaB = type(Point)
B = Point
+
class MetaC(MetaA, MetaB):
pass
+
+
class C(A, B):
__metaclass__ = MetaC
+
class D(C):
pass
+
class TestMetaClass(unittest.TestCase):
def testIt(self):
- w1 = C() # works
+ w1 = C() # works
w1.setX(1)
w1.setY(2)
- w2 = D() # should work!
+ w2 = D() # should work!
w2.setX(3)
w2.setY(4)
diff --git a/sources/shiboken6/tests/samplebinding/mixed_mi_test.py b/sources/shiboken6/tests/samplebinding/mixed_mi_test.py
index 776605a4d..fa8481600 100644
--- a/sources/shiboken6/tests/samplebinding/mixed_mi_test.py
+++ b/sources/shiboken6/tests/samplebinding/mixed_mi_test.py
@@ -52,5 +52,3 @@ class MixedInheritanceTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
-
diff --git a/sources/shiboken6/tests/samplebinding/modelindex_test.py b/sources/shiboken6/tests/samplebinding/modelindex_test.py
index 725105a9c..e23503eff 100644
--- a/sources/shiboken6/tests/samplebinding/modelindex_test.py
+++ b/sources/shiboken6/tests/samplebinding/modelindex_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import ModelIndex, ReferentModelIndex, PersistentModelIndex
+
class TestCastOperator(unittest.TestCase):
def testCastOperatorReturningValue(self):
@@ -30,4 +31,3 @@ class TestCastOperator(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/modelview_test.py b/sources/shiboken6/tests/samplebinding/modelview_test.py
index 0b5c657d9..b5663a04e 100644
--- a/sources/shiboken6/tests/samplebinding/modelview_test.py
+++ b/sources/shiboken6/tests/samplebinding/modelview_test.py
@@ -2,7 +2,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).'''
+'''Test case for objects that keep references to other object without owning them
+ (e.g. model/view relationships).'''
import os
import sys
@@ -17,9 +18,11 @@ from sample import ObjectModel, ObjectType, ObjectView
object_name = 'test object'
+
class MyObject(ObjectType):
pass
+
class ListModelKeepsReference(ObjectModel):
def __init__(self, parent=None):
ObjectModel.__init__(self, parent)
@@ -29,6 +32,7 @@ class ListModelKeepsReference(ObjectModel):
def data(self):
return self.obj
+
class ListModelDoesntKeepsReference(ObjectModel):
def data(self):
obj = MyObject()
@@ -55,4 +59,3 @@ class ModelViewTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/modifications_test.py b/sources/shiboken6/tests/samplebinding/modifications_test.py
index d1e70004f..dced14396 100644
--- a/sources/shiboken6/tests/samplebinding/modifications_test.py
+++ b/sources/shiboken6/tests/samplebinding/modifications_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import Modifications, Point, ByteArray
+
class ExtModifications(Modifications):
def __init__(self):
Modifications.__init__(self)
@@ -41,25 +42,15 @@ class ModificationsTest(unittest.TestCase):
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testClassMembersAvailability(self):
- '''Test if Modified class really have the expected members.'''
- expected_members = set(['OverloadedModFunc', 'OverloadedNone',
- 'Overloaded_ibiP', 'Overloaded_ibib',
- 'Overloaded_ibid', 'Overloaded_ibii',
- 'calculateArea', 'doublePlus', 'increment',
- 'multiplyPointCoordsPlusValue', 'name',
- 'pointToPair', 'overloaded', 'power',
- 'timesTen'])
- self.assertTrue(expected_members.issubset(dir(Modifications)))
-
def testRenamedMethodAvailability(self):
- '''Test if Modification class really have renamed the 'className' virtual method to 'name'.'''
+ '''Test if Modification class really have renamed the 'className'
+ virtual method to 'name'.'''
self.assertTrue('className' not in dir(Modifications))
self.assertTrue('name' in dir(Modifications))
def testReimplementationOfRenamedVirtualMethod(self):
- '''Test if class inheriting from Modification class have the reimplementation of renamed virtual method called.'''
+ '''Test if class inheriting from Modification class have the reimplementation
+ of renamed virtual method called.'''
em = ExtModifications()
self.assertEqual(self.mods.name(), 'Modifications')
self.assertEqual(em.name(), 'ExtModifications')
@@ -80,12 +71,14 @@ class ModificationsTest(unittest.TestCase):
self.assertEqual(self.mods.doublePlus(7), 14)
def testDefaultValueRemoval(self):
- '''Test if default value was removed from first argument of Modifications::increment(int).'''
+ '''Test if default value was removed from first argument of
+ Modifications::increment(int).'''
self.assertRaises(TypeError, self.mods.increment)
self.assertEqual(self.mods.increment(7), 8)
def testDefaultValueReplacement(self):
- '''Test if default values for both arguments of Modifications::power(int, int) were modified.'''
+ '''Test if default values for both arguments of Modifications::power(int, int)
+ were modified.'''
# original default values: int power(int base = 1, int exponent = 0);
self.assertNotEqual(self.mods.power(4), 1)
# modified default values: int power(int base = 2, int exponent = 1);
@@ -94,12 +87,14 @@ class ModificationsTest(unittest.TestCase):
self.assertEqual(self.mods.power(5, 3), 5**3)
def testSetNewDefaultValue(self):
- '''Test if default value was correctly set to 10 for first argument of Modifications::timesTen(int).'''
+ '''Test if default value was correctly set to 10 for first argument of
+ Modifications::timesTen(int).'''
self.assertEqual(self.mods.timesTen(7), 70)
self.assertEqual(self.mods.timesTen(), 100)
def testArgumentRemovalAndReturnTypeModificationWithTypesystemTemplates1(self):
- '''Test modifications to method signature and return value using type system templates (case 1).'''
+ '''Test modifications to method signature and return value using type
+ system templates (case 1).'''
result, ok = self.mods.pointToPair(Point(2, 5))
self.assertEqual(type(ok), bool)
self.assertEqual(type(result), tuple)
@@ -110,7 +105,8 @@ class ModificationsTest(unittest.TestCase):
self.assertEqual(result[1], 5.0)
def testArgumentRemovalAndReturnTypeModificationWithTypesystemTemplates2(self):
- '''Test modifications to method signature and return value using type system templates (case 2).'''
+ '''Test modifications to method signature and return value using
+ type system templates (case 2).'''
result, ok = self.mods.multiplyPointCoordsPlusValue(Point(2, 5), 4.1)
self.assertEqual(type(ok), bool)
self.assertEqual(type(result), float)
@@ -124,9 +120,11 @@ class ModificationsTest(unittest.TestCase):
self.assertEqual(self.mods.overloaded(1, True, 2), Modifications.Overloaded_ibii)
# the others weren't modified
self.assertEqual(self.mods.overloaded(1, True, 2, False), Modifications.Overloaded_ibib)
- self.assertEqual(self.mods.overloaded(1, False, 2, Point(3, 4)), Modifications.Overloaded_ibiP)
+ self.assertEqual(self.mods.overloaded(1, False, 2, Point(3, 4)),
+ Modifications.Overloaded_ibiP)
self.assertRaises(TypeError, self.mods.overloaded, 1, True, Point(2, 3), Point(4, 5))
- self.assertEqual(self.mods.over(1, True, Point(2, 3), Point(4, 5)), Modifications.Overloaded_ibPP)
+ self.assertEqual(self.mods.over(1, True, Point(2, 3), Point(4, 5)),
+ Modifications.Overloaded_ibPP)
def testPointArrayModification(self):
points = (Point(1, 1), Point(2, 2))
diff --git a/sources/shiboken6/tests/samplebinding/modified_constructor_test.py b/sources/shiboken6/tests/samplebinding/modified_constructor_test.py
index d4b65a88a..9791a3491 100644
--- a/sources/shiboken6/tests/samplebinding/modified_constructor_test.py
+++ b/sources/shiboken6/tests/samplebinding/modified_constructor_test.py
@@ -4,7 +4,6 @@
'''Tests cases for ConstructorWithModifiedArgument class.'''
-import sys
import os
import sys
import unittest
@@ -14,7 +13,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ModifiedConstructor
class ConstructorWithModifiedArgumentTest(unittest.TestCase):
@@ -24,6 +23,6 @@ class ConstructorWithModifiedArgumentTest(unittest.TestCase):
sampleClass = ModifiedConstructor("10")
self.assertTrue(sampleClass.retrieveValue(), 10)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/modifiedvirtualmethods_test.py b/sources/shiboken6/tests/samplebinding/modifiedvirtualmethods_test.py
index ae090f8e3..dcb487f1a 100644
--- a/sources/shiboken6/tests/samplebinding/modifiedvirtualmethods_test.py
+++ b/sources/shiboken6/tests/samplebinding/modifiedvirtualmethods_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import VirtualMethods, Str
+
class ExtendedVirtualMethods(VirtualMethods):
def __init__(self):
VirtualMethods.__init__(self)
@@ -61,7 +62,7 @@ class ExtendedVirtualMethods(VirtualMethods):
self.callMe_called += 1
def getMargins(self):
- return tuple([m*2 for m in VirtualMethods.getMargins(self)])
+ return tuple([m * 2 for m in VirtualMethods.getMargins(self)])
class VirtualMethodsTest(unittest.TestCase):
@@ -185,7 +186,8 @@ class VirtualMethodsTest(unittest.TestCase):
removed_arg_value = 2011
default_value = 3000
result = self.evm.callSum4(a0, removed_arg_value, a1)
- self.assertEqual(result, (a0 - removed_arg_value + a1 + default_value) * self.evm.multiplier)
+ self.assertEqual(result,
+ (a0 - removed_arg_value + a1 + default_value) * self.evm.multiplier)
self.assertTrue(self.evm.sum4_called)
def testOverridenMethodResultModification(self):
@@ -217,15 +219,15 @@ class VirtualMethodsTest(unittest.TestCase):
def testExtendedAllArgumentsRemoved(self):
values = (10, 20, 30, 40)
self.evm.setMargins(*values)
- double = tuple([m*2 for m in values])
+ double = tuple([m * 2 for m in values])
self.assertEqual(self.evm.getMargins(), double)
def testExtendedAllArgumentsRemovedCallVirtual(self):
values = (10, 20, 30, 40)
self.evm.setMargins(*values)
- double = tuple([m*2 for m in values])
+ double = tuple([m * 2 for m in values])
self.assertEqual(self.evm.callGetMargins(), double)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/multi_cpp_inheritance_test.py b/sources/shiboken6/tests/samplebinding/multi_cpp_inheritance_test.py
index e655b8051..fc6b26c3f 100644
--- a/sources/shiboken6/tests/samplebinding/multi_cpp_inheritance_test.py
+++ b/sources/shiboken6/tests/samplebinding/multi_cpp_inheritance_test.py
@@ -13,72 +13,85 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectType, Point, Str
+
class SimpleUseCase(ObjectType, Str):
def __init__(self, name):
ObjectType.__init__(self)
Str.__init__(self, name)
+
class SimpleUseCaseReverse(Str, ObjectType):
def __init__(self, name):
ObjectType.__init__(self)
Str.__init__(self, name)
+
class SimpleUseCase2(SimpleUseCase):
def __init__(self, name):
SimpleUseCase.__init__(self, name)
+
class ComplexUseCase(SimpleUseCase2, Point):
def __init__(self, name):
SimpleUseCase2.__init__(self, name)
Point.__init__(self)
+
class ComplexUseCaseReverse(Point, SimpleUseCase2):
def __init__(self, name):
SimpleUseCase2.__init__(self, name)
Point.__init__(self)
+
class MultipleCppDerivedTest(unittest.TestCase):
- def testInstanciation(self):
+ def testInstantiation(self):
s = SimpleUseCase("Hi")
self.assertEqual(s, "Hi")
s.setObjectName(s)
self.assertEqual(s.objectName(), "Hi")
- def testInstanciation2(self):
+ def testInstantiation2(self):
s = SimpleUseCase2("Hi")
self.assertEqual(s, "Hi")
s.setObjectName(s)
self.assertEqual(s.objectName(), "Hi")
- def testComplexInstanciation(self):
+ def testComplexInstantiation(self):
c = ComplexUseCase("Hi")
self.assertEqual(c, "Hi")
c.setObjectName(c)
self.assertEqual(c.objectName(), "Hi")
- c.setX(2);
+ c.setX(2)
self.assertEqual(c.x(), 2)
+
class MultipleCppDerivedReverseTest(unittest.TestCase):
- def testInstanciation(self):
+ def testInstantiation(self):
s = SimpleUseCaseReverse("Hi")
self.assertEqual(s, "Hi")
s.setObjectName(s)
self.assertEqual(s.objectName(), "Hi")
- def testInstanciation2(self):
+ def testInstantiation2(self):
s = SimpleUseCase2("Hi")
self.assertEqual(s, "Hi")
s.setObjectName(s)
self.assertEqual(s.objectName(), "Hi")
- def testComplexInstanciation(self):
- c = ComplexUseCaseReverse("Hi")
- c.setObjectName(c)
- self.assertEqual(c.objectName(), "Hi")
- c.setX(2);
- self.assertEqual(c, Point(2, 0))
+ def testComplexInstantiation(self):
+ # PYSIDE-1564: This test can no longer work because of this MRO:
+ # ('ComplexUseCaseReverse', 'Point', 'SimpleUseCase2', 'SimpleUseCase',
+ # 'ObjectType', 'Str', 'Object', 'object')
+ # By multiple inheritance Point would be called first but has no argument.
+ with self.assertRaises(TypeError):
+ c = ComplexUseCaseReverse("Hi") # noqa: F841
+ # c.setObjectName(c)
+ # self.assertEqual(c.objectName(), "Hi")
+ # c.setX(2);
+ # self.assertEqual(c, Point(2, 0))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/multiple_derived_test.py b/sources/shiboken6/tests/samplebinding/multiple_derived_test.py
index 46e44601d..7497714a8 100644
--- a/sources/shiboken6/tests/samplebinding/multiple_derived_test.py
+++ b/sources/shiboken6/tests/samplebinding/multiple_derived_test.py
@@ -13,17 +13,20 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import Base1, Base2, Base3, Base4, Base5, Base6
+from sample import Base1, Base2
from sample import MDerived1, MDerived2, MDerived3, MDerived4, MDerived5, SonOfMDerived1
+
class ExtMDerived1(MDerived1):
def __init__(self):
MDerived1.__init__(self)
self.multiplier = 20
self.base2Method_called = False
+
def base2Method(self):
return Base2.base2Method(self) * self.multiplier
+
class MultipleDerivedTest(unittest.TestCase):
'''Test cases for multiple inheritance'''
@@ -40,19 +43,22 @@ class MultipleDerivedTest(unittest.TestCase):
self.assertTrue(issubclass(MDerived1, Base2))
def testCallToFunctionWithBase1ArgumentThatCastsBackToMDerived1(self):
- '''MDerived1 is passed as an Base1 argument to a method that returns it casted back to MDerived1.'''
+ '''MDerived1 is passed as an Base1 argument to a method that returns
+ it casted back to MDerived1.'''
a = MDerived1()
b = MDerived1.transformFromBase1(a)
self.assertEqual(a, b)
def testCallToFunctionWithBase2ArgumentThatCastsBackToMDerived1(self):
- '''MDerived1 is passed as an Base2 argument to a method that returns it casted back to MDerived1.'''
+ '''MDerived1 is passed as an Base2 argument to a method that returns
+ it casted back to MDerived1.'''
a = MDerived1()
b = MDerived1.transformFromBase2(a)
self.assertEqual(a, b)
def testPythonClassIsInstance(self):
- '''Python defined class ExtMDerived1 is instance of its parents MDerived1, Base1 and Base2.'''
+ '''Python defined class ExtMDerived1 is instance of its parents
+ MDerived1, Base1 and Base2.'''
a = ExtMDerived1()
self.assertTrue(isinstance(a, ExtMDerived1))
self.assertTrue(isinstance(a, MDerived1))
@@ -60,14 +66,16 @@ class MultipleDerivedTest(unittest.TestCase):
self.assertTrue(isinstance(a, Base2))
def testPythonClassIsSubclass(self):
- '''Python defined class ExtMDerived1 is subclass of its parents MDerived1, Base1 and Base2.'''
+ '''Python defined class ExtMDerived1 is subclass of its parents
+ MDerived1, Base1 and Base2.'''
self.assertTrue(issubclass(ExtMDerived1, MDerived1))
self.assertTrue(issubclass(ExtMDerived1, Base1))
self.assertTrue(issubclass(ExtMDerived1, Base2))
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived1ToBases(self):
- '''MDerived1 is casted by C++ to its parents and the binding must return the MDerived1 wrapper.'''
+ '''MDerived1 is casted by C++ to its parents and the binding must return the
+ MDerived1 wrapper.'''
a = MDerived1()
refcnt = sys.getrefcount(a)
b1 = a.castToBase1()
@@ -80,7 +88,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromExtMDerived1ToMDerived1Bases(self):
- '''Python defined class ExtMDerived1 is casted by C++ to MDerived1 parents and the binding must return the correct ExtMDerived1 instance.'''
+ '''Python defined class ExtMDerived1 is casted by C++ to MDerived1 parents
+ and the binding must return the correct ExtMDerived1 instance.'''
a = ExtMDerived1()
refcnt = sys.getrefcount(a)
b1 = a.castToBase1()
@@ -95,7 +104,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromSonOfMDerived1ToBases(self):
- '''SonOfMDerived1 is casted by C++ to its parents and the binding must return the SonOfMDerived1 wrapper.'''
+ '''SonOfMDerived1 is casted by C++ to its parents and the binding must return
+ the SonOfMDerived1 wrapper.'''
a = SonOfMDerived1()
refcnt = sys.getrefcount(a)
md1 = a.castToMDerived1()
@@ -116,7 +126,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived2ToBases(self):
- '''MDerived2 is casted by C++ to its parents and the binding must return the MDerived2 wrapper.'''
+ '''MDerived2 is casted by C++ to its parents and the binding must
+ return the MDerived2 wrapper.'''
a = MDerived2()
refcnt = sys.getrefcount(a)
b3 = a.castToBase3()
@@ -135,7 +146,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived3ToBases(self):
- '''MDerived3 is casted by C++ to its parents and the binding must return the MDerived3 wrapper.'''
+ '''MDerived3 is casted by C++ to its parents and the binding must
+ return the MDerived3 wrapper.'''
a = MDerived3()
refcnt = sys.getrefcount(a)
md1 = a.castToMDerived1()
@@ -166,7 +178,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived4ToBases(self):
- '''MDerived4 is casted by C++ to its parents and the binding must return the MDerived4 wrapper.'''
+ '''MDerived4 is casted by C++ to its parents and the binding must
+ return the MDerived4 wrapper.'''
a = MDerived4()
refcnt = sys.getrefcount(a)
b3 = a.castToBase3()
@@ -179,7 +192,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived5ToBases(self):
- '''MDerived5 is casted by C++ to its parents and the binding must return the MDerived5 wrapper.'''
+ '''MDerived5 is casted by C++ to its parents and the binding must
+ return the MDerived5 wrapper.'''
a = MDerived5()
refcnt = sys.getrefcount(a)
b3 = a.castToBase3()
@@ -192,7 +206,8 @@ class MultipleDerivedTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testCastFromMDerived3ToBase3(self):
- '''MDerived3 is casted by C++ to Base3 grandparent using both the inherited and reimplement castToBase3 methods.'''
+ '''MDerived3 is casted by C++ to Base3 grandparent using both the inherited
+ and reimplement castToBase3 methods.'''
a = MDerived3()
refcnt = sys.getrefcount(a)
b3_reimplemented = a.castToBase3()
@@ -203,6 +218,6 @@ class MultipleDerivedTest(unittest.TestCase):
self.assertEqual(a, b3_inherited)
self.assertEqual(sys.getrefcount(a), refcnt + 2)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/namespace_test.py b/sources/shiboken6/tests/samplebinding/namespace_test.py
index a7833c921..64a6792ac 100644
--- a/sources/shiboken6/tests/samplebinding/namespace_test.py
+++ b/sources/shiboken6/tests/samplebinding/namespace_test.py
@@ -13,12 +13,9 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import SampleNamespace
from shiboken_test_helper import objectFullname
-from shiboken6 import Shiboken
-_init_pyside_extension() # trigger bootstrap
-
from shibokensupport.signature import get_signature
# For tests of invisible namespaces, see
@@ -27,25 +24,17 @@ from shibokensupport.signature import get_signature
class TestVariablesUnderNamespace(unittest.TestCase):
def testIt(self):
- self.assertEqual(SampleNamespace.variableInNamespace, 42)
+ self.assertEqual(SampleNamespace.variableInNamespace, 42)
class TestClassesUnderNamespace(unittest.TestCase):
def testIt(self):
- if sys.pyside63_option_python_enum:
- c1 = SampleNamespace.SomeClass()
- e1 = SampleNamespace.SomeClass.ProtectedEnum(0)
- c2 = SampleNamespace.SomeClass.SomeInnerClass()
- e2 = SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum(0)
- c3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough()
- e3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum(0)
- else:
- c1 = SampleNamespace.SomeClass()
- e1 = SampleNamespace.SomeClass.ProtectedEnum()
- c2 = SampleNamespace.SomeClass.SomeInnerClass()
- e2 = SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum()
- c3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough()
- e3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum()
+ c1 = SampleNamespace.SomeClass() # noqa F841
+ e1 = SampleNamespace.SomeClass.ProtectedEnum() # noqa F841
+ c2 = SampleNamespace.SomeClass.SomeInnerClass() # noqa F841
+ e2 = SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum() # noqa F841
+ c3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough() # noqa F841
+ e3 = SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum(0) # noqa F841
def testFunctionAddedOnNamespace(self):
res = SampleNamespace.ImInsideANamespace(2, 2)
@@ -53,24 +42,26 @@ class TestClassesUnderNamespace(unittest.TestCase):
def testTpNames(self):
self.assertEqual(str(SampleNamespace.SomeClass),
- "<class 'sample.SampleNamespace.SomeClass'>")
+ "<class 'sample.SampleNamespace.SomeClass'>")
self.assertEqual(str(SampleNamespace.SomeClass.ProtectedEnum),
- "<enum 'ProtectedEnum'>" if sys.pyside63_option_python_enum else
- "<class 'sample.SampleNamespace.SomeClass.ProtectedEnum'>")
+ "<enum 'ProtectedEnum'>")
self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum),
- "<enum 'ProtectedEnum'>" if sys.pyside63_option_python_enum else
- "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum'>")
+ "<enum 'ProtectedEnum'>")
self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough),
- "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>")
- self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum),
- "<enum 'NiceEnum'>" if sys.pyside63_option_python_enum else
- "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>")
+ "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>") # noqa: E501
+ self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), # noqa: E501
+ "<enum 'NiceEnum'>")
# Test if enum inside of class is correct represented
- self.assertEqual(objectFullname(get_signature(SampleNamespace.enumInEnumOut).parameters['in_'].annotation),
- "sample.SampleNamespace.InValue")
- self.assertEqual(objectFullname(get_signature(SampleNamespace.enumAsInt).parameters['value'].annotation),
- "sample.SampleNamespace.SomeClass.PublicScopedEnum")
+ an = objectFullname(get_signature(SampleNamespace.enumInEnumOut).parameters['in_'].annotation) # noqa: E501
+ self.assertEqual(an, "sample.SampleNamespace.InValue")
+ an = objectFullname(get_signature(SampleNamespace.enumAsInt).parameters['value'].annotation)
+ self.assertEqual(an, "sample.SampleNamespace.SomeClass.PublicScopedEnum")
+
+ def testInlineNamespaces(self):
+ cls = SampleNamespace.ClassWithinInlineNamespace()
+ cls.setValue(SampleNamespace.EWIN_Value1)
+ self.assertEqual(cls.value(), SampleNamespace.EWIN_Value1)
if __name__ == '__main__':
diff --git a/sources/shiboken6/tests/samplebinding/newdivision_test.py b/sources/shiboken6/tests/samplebinding/newdivision_test.py
index 6286dcfc9..0e7dfbee1 100644
--- a/sources/shiboken6/tests/samplebinding/newdivision_test.py
+++ b/sources/shiboken6/tests/samplebinding/newdivision_test.py
@@ -10,16 +10,16 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Point
class TestNewDivision(unittest.TestCase):
def testIt(self):
p = Point(4, 4)
- p2 = p/2
+ p2 = p / 2
self.assertEqual(p2, Point(2, 2))
+
if __name__ == "__main__":
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/nondefaultctor_test.py b/sources/shiboken6/tests/samplebinding/nondefaultctor_test.py
index 3892508ae..bc8d29e50 100644
--- a/sources/shiboken6/tests/samplebinding/nondefaultctor_test.py
+++ b/sources/shiboken6/tests/samplebinding/nondefaultctor_test.py
@@ -15,14 +15,17 @@ init_paths()
from sample import NonDefaultCtor
+
class DerivedNonDefaultCtor (NonDefaultCtor):
def returnMyselfVirtual(self):
- return NonDefaultCtor(self.value()+1)
+ return NonDefaultCtor(self.value() + 1)
+
class AnotherDerivedNonDefaultCtor (NonDefaultCtor):
def __init__(self, some_string):
pass
+
class NonDefaultCtorTest(unittest.TestCase):
def testNonDefaultCtor(self):
@@ -43,8 +46,8 @@ class NonDefaultCtorTest(unittest.TestCase):
self.assertEqual(c.callReturnMyselfVirtual().value(), 4)
def testCtorOverload(self):
- c = AnotherDerivedNonDefaultCtor("testing")
+ c = AnotherDerivedNonDefaultCtor("testing") # noqa: F841
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/nontypetemplate_test.py b/sources/shiboken6/tests/samplebinding/nontypetemplate_test.py
index fa28abc6d..a10547728 100644
--- a/sources/shiboken6/tests/samplebinding/nontypetemplate_test.py
+++ b/sources/shiboken6/tests/samplebinding/nontypetemplate_test.py
@@ -21,6 +21,7 @@ init_paths()
from sample import IntArray2, IntArray3
+
class NonTypeTemplateTest(unittest.TestCase):
def testNonTypeTemplate(self):
@@ -32,7 +33,7 @@ class NonTypeTemplateTest(unittest.TestCase):
def testArrayInitializer(self):
if not hasNumPy:
return
- array3 = IntArray3(numpy.array([1, 2, 3], dtype = 'int32'))
+ array3 = IntArray3(numpy.array([1, 2, 3], dtype='int32'))
self.assertEqual(array3.sum(), 6)
diff --git a/sources/shiboken6/tests/samplebinding/nonzero_test.py b/sources/shiboken6/tests/samplebinding/nonzero_test.py
index d2a30c7ef..7be239fc4 100644
--- a/sources/shiboken6/tests/samplebinding/nonzero_test.py
+++ b/sources/shiboken6/tests/samplebinding/nonzero_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import Color, Brush
+
class TestNonZeroOperator(unittest.TestCase):
def testColor(self):
"""Color has a Qt-style isNull()"""
diff --git a/sources/shiboken6/tests/samplebinding/numericaltypedef_test.py b/sources/shiboken6/tests/samplebinding/numericaltypedef_test.py
index 9539469a1..f714a4fc8 100644
--- a/sources/shiboken6/tests/samplebinding/numericaltypedef_test.py
+++ b/sources/shiboken6/tests/samplebinding/numericaltypedef_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import SizeF
+
class NumericalTypedefTest(unittest.TestCase):
def testNumericalTypedefExact(self):
@@ -32,5 +33,6 @@ class NumericalTypedefTest(unittest.TestCase):
self.assertEqual(SizeF.passTypedefOfUnsignedShort(321), 321)
self.assertNotEqual(SizeF.passTypedefOfUnsignedShort(123), 0)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/numpy_test.py b/sources/shiboken6/tests/samplebinding/numpy_test.py
index af1e6d1bf..42094a463 100644
--- a/sources/shiboken6/tests/samplebinding/numpy_test.py
+++ b/sources/shiboken6/tests/samplebinding/numpy_test.py
@@ -8,7 +8,7 @@ try:
if bool(sysconfig.get_config_var('Py_DEBUG')):
sys.exit(0)
import numpy
-except:
+except: # noqa: E722
sys.exit(0)
import os
@@ -21,6 +21,7 @@ from shiboken_paths import init_paths
init_paths()
from sample import PointF
+
class TestNumpyTypes(unittest.TestCase):
def testNumpyConverted(self):
@@ -35,6 +36,6 @@ class TestNumpyTypes(unittest.TestCase):
self.assertAlmostEqual(p.x(), x)
self.assertAlmostEqual(p.y(), y)
+
if __name__ == "__main__":
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/objecttype_test.py b/sources/shiboken6/tests/samplebinding/objecttype_test.py
index 6e90bfb35..ead68ba13 100644
--- a/sources/shiboken6/tests/samplebinding/objecttype_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttype_test.py
@@ -68,7 +68,7 @@ class ObjectTypeTest(unittest.TestCase):
def testNextInFocusChainCycle(self):
parent = ObjectType()
child = ObjectType(parent)
- next_focus = child.nextInFocusChain()
+ next_focus = child.nextInFocusChain() # noqa: F841
Shiboken.invalidate(parent)
@@ -105,5 +105,6 @@ class ObjectTypeTest(unittest.TestCase):
with self.assertRaises(AttributeError):
o.typo
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/objecttype_with_named_args_test.py b/sources/shiboken6/tests/samplebinding/objecttype_with_named_args_test.py
index 4e552e887..285e2313b 100644
--- a/sources/shiboken6/tests/samplebinding/objecttype_with_named_args_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttype_with_named_args_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import ObjectType
+
class NamedArgsTest(unittest.TestCase):
def testOneArgument(self):
@@ -35,18 +36,15 @@ class NamedArgsTest(unittest.TestCase):
o.setObjectNameWithSize(size=6, name="pyside")
self.assertEqual(o.objectName(), "pyside")
-
def testUseDefaultValues(self):
o = ObjectType()
o.setObjectNameWithSize(size=3)
- self.assertEqual(o.objectName(), "<un") # use name='unknown' default argument
+ self.assertEqual(o.objectName(), "<un") # use name='unknown' default argument
o.setObjectSplittedName("")
- self.assertEqual(o.objectName(), "<unknown>") # user prefix='<unk' and suffix='nown>'
-
+ self.assertEqual(o.objectName(), "<unknown>") # user prefix='<unk' and suffix='nown>'
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/objecttypebyvalue_test.py b/sources/shiboken6/tests/samplebinding/objecttypebyvalue_test.py
index 9dd3baf63..8f74af3ab 100644
--- a/sources/shiboken6/tests/samplebinding/objecttypebyvalue_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttypebyvalue_test.py
@@ -10,7 +10,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectTypeByValue
class ObjectTypeByValueTest (unittest.TestCase):
@@ -22,5 +22,6 @@ class ObjectTypeByValueTest (unittest.TestCase):
# just to make sure it will segfault
obj.prop.protectedValueTypeProperty.setY(2.0)
+
if __name__ == "__main__":
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/objecttypelayout_test.py b/sources/shiboken6/tests/samplebinding/objecttypelayout_test.py
index ea30f103e..677b89281 100644
--- a/sources/shiboken6/tests/samplebinding/objecttypelayout_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttypelayout_test.py
@@ -14,7 +14,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectType, ObjectTypeLayout
class ObjectTypeLayoutTest(unittest.TestCase):
@@ -22,16 +22,15 @@ class ObjectTypeLayoutTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testOwnershipOverride(self):
- l = ObjectTypeLayout()
+ lt = ObjectTypeLayout()
- o1 = ObjectType(l)
+ o1 = ObjectType(lt)
o1.setObjectName('o1')
self.assertEqual(sys.getrefcount(o1), 3)
- l.takeChild('o1')
+ lt.takeChild('o1')
self.assertEqual(sys.getrefcount(o1), 2)
-
def testSetNullLayout(self):
'''ObjectType.setLayout(0).'''
o2 = ObjectType()
@@ -57,7 +56,7 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertEqual(c3.parent(), None)
p1.setLayout(layout)
- del p1 # This must kill c1, c2 and c3
+ del p1 # This must kill c1, c2 and c3
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
@@ -81,7 +80,7 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertEqual(c3.parent(), None)
p1.setLayout(layout)
- del p1 # This must kill c1, c2 and c3
+ del p1 # This must kill c1, c2 and c3
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
@@ -91,7 +90,8 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, layout.objectName)
def testObjectTypeLayoutTransference(self):
- '''Transfer a layout from one ObjectType to another, so that all the items in the layout get reparented.'''
+ '''Transfer a layout from one ObjectType to another, so that all the items in
+ the layout get reparented.'''
p1 = ObjectType()
p2 = ObjectType()
c1 = ObjectType()
@@ -154,7 +154,8 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, l2.objectName)
def testObjectTypeLayoutInsideAnotherLayoutAndEveryoneCreatedInCpp(self):
- '''Adds one ObjectTypeLayout to another and sets the parent to an ObjectType. All the objects are created in C++.'''
+ '''Adds one ObjectTypeLayout to another and sets the parent to an ObjectType.
+ All the objects are created in C++.'''
p1 = ObjectType.create()
l1 = ObjectTypeLayout.create()
@@ -192,7 +193,8 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, l2.objectName)
def testTransferNestedLayoutsBetweenObjects(self):
- '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType and then transfer it to another object.'''
+ '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType
+ and then transfer it to another object.'''
p1 = ObjectType()
p2 = ObjectType()
@@ -243,8 +245,8 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, l2.objectName)
def testTransferNestedLayoutsBetweenObjectsAndEveryoneCreatedInCpp(self):
- '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType and then transfer it to another object.
- All the objects are created in C++.'''
+ '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType and then
+ transfer it to another object. All the objects are created in C++.'''
p1 = ObjectType.create()
p2 = ObjectType.create()
@@ -294,6 +296,6 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, l1.objectName)
self.assertRaises(RuntimeError, l2.objectName)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/objecttypeoperators_test.py b/sources/shiboken6/tests/samplebinding/objecttypeoperators_test.py
index ae5936635..ceeee6c8d 100644
--- a/sources/shiboken6/tests/samplebinding/objecttypeoperators_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttypeoperators_test.py
@@ -10,7 +10,8 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import ObjectTypeOperators
+
class ObjectTypeOperatorsTest(unittest.TestCase):
@@ -26,7 +27,7 @@ class ObjectTypeOperatorsTest(unittest.TestCase):
def testPointerOpeators(self):
a = ObjectTypeOperators("a")
- b = ObjectTypeOperators("b")
+ b = ObjectTypeOperators("b") # noqa: F841
self.assertEqual(a + "bc", "abc")
self.assertEqual("bc" + a, "bca")
self.assertEqual("a", a)
@@ -36,5 +37,6 @@ class ObjectTypeOperatorsTest(unittest.TestCase):
a = ObjectTypeOperators("a")
self.assertNotEqual(a, "b")
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py b/sources/shiboken6/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py
index 68e5edecc..5fa6f824e 100644
--- a/sources/shiboken6/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py
+++ b/sources/shiboken6/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py
@@ -12,6 +12,7 @@ from shiboken_paths import init_paths
init_paths()
from sample import ObjectTypeHolder
+
class TestObjectTypeReferenceAsVirtualMethodArgument(unittest.TestCase):
def testBasic(self):
@@ -25,5 +26,6 @@ class TestObjectTypeReferenceAsVirtualMethodArgument(unittest.TestCase):
holder = Holder('TheObjectFromC++')
self.assertEqual(holder.callPassObjectTypeAsReference(), 'ThisIsTheObjectFromC++')
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/oddbool_test.py b/sources/shiboken6/tests/samplebinding/oddbool_test.py
index 466ddba82..87a8cdb1f 100644
--- a/sources/shiboken6/tests/samplebinding/oddbool_test.py
+++ b/sources/shiboken6/tests/samplebinding/oddbool_test.py
@@ -15,11 +15,13 @@ init_paths()
from sample import OddBoolUser, ComparisonTester, SpaceshipComparisonTester
+
class DerivedOddBoolUser (OddBoolUser):
def returnMyselfVirtual(self):
return OddBoolUser()
pass
+
class OddBoolTest(unittest.TestCase):
def testOddBoolUser(self):
@@ -30,13 +32,13 @@ class OddBoolTest(unittest.TestCase):
self.assertEqual(obuTrue.oddBool(), True)
self.assertEqual(obuTrue.callInvertedOddBool(), False)
- self.assertEqual(obuTrue.oddBool() == True, True)
- self.assertEqual(False == obuFalse.oddBool(), True)
- self.assertEqual(obuTrue.oddBool() == obuFalse.oddBool(), False)
+ self.assertTrue(obuTrue.oddBool())
+ self.assertFalse(obuFalse.oddBool())
+ self.assertTrue(obuTrue.oddBool() != obuFalse.oddBool())
- self.assertEqual(obuFalse.oddBool() != True, True)
- self.assertEqual(True != obuFalse.oddBool(), True)
- self.assertEqual(obuTrue.oddBool() != obuFalse.oddBool(), True)
+ self.assertFalse(obuFalse.oddBool())
+ self.assertFalse(obuFalse.oddBool())
+ self.assertTrue(obuTrue.oddBool() != obuFalse.oddBool())
def testVirtuals(self):
dobu = DerivedOddBoolUser()
diff --git a/sources/shiboken6/tests/samplebinding/onlycopyclass_test.py b/sources/shiboken6/tests/samplebinding/onlycopyclass_test.py
index 3bdf431ad..bcb154c52 100644
--- a/sources/shiboken6/tests/samplebinding/onlycopyclass_test.py
+++ b/sources/shiboken6/tests/samplebinding/onlycopyclass_test.py
@@ -13,6 +13,7 @@ init_paths()
from sample import OnlyCopy, FriendOfOnlyCopy
+
class ClassWithOnlyCopyCtorTest(unittest.TestCase):
def testGetOne(self):
obj = FriendOfOnlyCopy.createOnlyCopy(123)
@@ -34,5 +35,6 @@ class ClassWithOnlyCopyCtorTest(unittest.TestCase):
obj = FriendOfOnlyCopy.createOnlyCopy(123)
self.assertEqual(obj.value(), OnlyCopy.getValueFromReference(obj))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/overflow_test.py b/sources/shiboken6/tests/samplebinding/overflow_test.py
index bb98f313d..84442306a 100644
--- a/sources/shiboken6/tests/samplebinding/overflow_test.py
+++ b/sources/shiboken6/tests/samplebinding/overflow_test.py
@@ -13,7 +13,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import (Point, doubleLongLong, doubleShort, doubleUnsignedInt,
+ doubleUnsignedLongLong)
class OverflowTest(unittest.TestCase):
@@ -25,14 +26,16 @@ class OverflowTest(unittest.TestCase):
return super().assertRaises(*args, **kwds)
def testUnsignedInt(self):
- '''C++ function receives an unsigned int argument and raise OverflowError if the value is negative.'''
+ '''C++ function receives an unsigned int argument and raise OverflowError
+ if the value is negative.'''
val = 100
self.assertEqual(doubleUnsignedInt(val), 2 * val)
val *= -1
self.assertRaises(OverflowError, doubleUnsignedInt, val)
def testLongLong(self):
- '''C++ function receives an long long argument and raise OverflowError if the value is negative.'''
+ '''C++ function receives an long long argument and raise OverflowError
+ if the value is negative.'''
val = 100
self.assertEqual(doubleLongLong(val), 2 * val)
val = int(100)
@@ -41,7 +44,8 @@ class OverflowTest(unittest.TestCase):
self.assertRaises(OverflowError, doubleLongLong, val)
def testUnsignedLongLong(self):
- '''C++ function receives an unsigned long long argument and raise OverflowError if the value is negative.'''
+ '''C++ function receives an unsigned long long argument and raise OverflowError
+ if the value is negative.'''
val = 100
self.assertEqual(doubleUnsignedLongLong(val), 2 * val)
val = int(100)
@@ -59,13 +63,13 @@ class OverflowTest(unittest.TestCase):
def testShortOverflow(self):
'''Calls function with short parameter using an overflowing value.'''
doubleShort(-3)
- self.assertRaises(OverflowError, doubleShort, 0xFFFF*-1)
+ self.assertRaises(OverflowError, doubleShort, 0xFFFF * -1)
self.assertRaises(OverflowError, doubleShort, 0xFFFF + 1)
def testOverflowOnCtor(self):
'''Calls object ctor with int parameter using overflowing values.'''
self.assertRaises(OverflowError, Point, 42415335332353253, 42415335332353253)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/overload_sorting_test.py b/sources/shiboken6/tests/samplebinding/overload_sorting_test.py
index 03da96581..060d91510 100644
--- a/sources/shiboken6/tests/samplebinding/overload_sorting_test.py
+++ b/sources/shiboken6/tests/samplebinding/overload_sorting_test.py
@@ -13,11 +13,14 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import (CustomOverloadSequence, ImplicitBase, ImplicitConv,
+ ImplicitTarget, SortedOverload)
+
class Dummy(object):
pass
+
class SimpleOverloadSorting(unittest.TestCase):
def setUp(self):
@@ -63,6 +66,7 @@ class DeepOverloadSorting(unittest.TestCase):
'''Deep Overload - (int, ImplicitBase *)'''
self.assertEqual(self.obj.overloadDeep(1, ImplicitBase()), "ImplicitBase")
+
class EnumOverIntSorting(unittest.TestCase):
def testEnumOverInt(self):
ic = ImplicitConv(ImplicitConv.CtorTwo)
diff --git a/sources/shiboken6/tests/samplebinding/overload_test.py b/sources/shiboken6/tests/samplebinding/overload_test.py
index d6bd90877..62fa8d8d2 100644
--- a/sources/shiboken6/tests/samplebinding/overload_test.py
+++ b/sources/shiboken6/tests/samplebinding/overload_test.py
@@ -21,11 +21,10 @@ def raisesWithErrorMessage(func, arguments, errorType, errorMsg):
try:
func(*arguments)
return False
- except Exception as err:
- if type(err) != TypeError:
- return False
- if not errorMsg in str(err):
- return False
+ except TypeError as err:
+ return errorMsg in str(err)
+ except Exception:
+ return False
return True
@@ -178,12 +177,13 @@ class OverloadTest(unittest.TestCase):
def testAcceptSequencePyObject(self):
# Overload.acceptSequence(void*)
overload = Overload()
+
class Foo(object):
pass
+
foo = Foo()
self.assertEqual(overload.acceptSequence(foo), Overload.Function5)
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/overloadwithdefault_test.py b/sources/shiboken6/tests/samplebinding/overloadwithdefault_test.py
index 199297415..269b97299 100644
--- a/sources/shiboken6/tests/samplebinding/overloadwithdefault_test.py
+++ b/sources/shiboken6/tests/samplebinding/overloadwithdefault_test.py
@@ -39,6 +39,6 @@ class OverloadTest(unittest.TestCase):
overload = Overload()
self.assertEqual(overload.strBufferOverloads(bytes('', "UTF-8"), 0), Overload.Function1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_argument_invalidation_test.py b/sources/shiboken6/tests/samplebinding/ownership_argument_invalidation_test.py
index 8a3cdf490..8a55d3ab8 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_argument_invalidation_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_argument_invalidation_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Polygon, Point
+
class WrapperValidityOfArgumentsTest(unittest.TestCase):
'''Wrapper validity tests for arguments.'''
@@ -25,17 +26,19 @@ class WrapperValidityOfArgumentsTest(unittest.TestCase):
self.assertRaises(RuntimeError, Polygon.doublePolygonScale, poly)
def testInvalidArgumentToConstructor(self):
- '''Call to constructor using invalidated Python wrapper as argument should raise RuntimeError.'''
+ '''Call to constructor using invalidated Python wrapper as argument
+ should raise RuntimeError.'''
pt = Point(1, 2)
Polygon.stealOwnershipFromPython(pt)
self.assertRaises(RuntimeError, Polygon, pt)
def testInvalidArgumentWithImplicitConversion(self):
- '''Call to method using invalidated Python wrapper to be implicitly converted should raise RuntimeError.'''
+ '''Call to method using invalidated Python wrapper to be implicitly converted
+ should raise RuntimeError.'''
pt = Point(1, 2)
Polygon.stealOwnershipFromPython(pt)
self.assertRaises(RuntimeError, Polygon.doublePolygonScale, pt)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_cpp_test.py b/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_cpp_test.py
index 2c789a72a..25c6fea26 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_cpp_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_cpp_test.py
@@ -30,5 +30,6 @@ class DeleteChildInCpp(unittest.TestCase):
self.assertRaises(RuntimeError, child.objectName)
self.assertEqual(parent.objectName(), 'parent')
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_python_test.py b/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_python_test.py
index b6f5ce235..3ae186815 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_python_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_delete_child_in_python_test.py
@@ -35,5 +35,6 @@ class DeleteChildInPython(unittest.TestCase):
new_child = parent.children()[0]
self.assertEqual(new_child.objectName(), name)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/ownership_delete_parent_test.py b/sources/shiboken6/tests/samplebinding/ownership_delete_parent_test.py
index 044ef9af6..8f654639c 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_delete_parent_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_delete_parent_test.py
@@ -33,7 +33,7 @@ class DeleteParentTest(unittest.TestCase):
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
self.assertRaises(RuntimeError, child.objectName)
- self.assertEqual(sys.getrefcount(child), refcount_before-1)
+ self.assertEqual(sys.getrefcount(child), refcount_before - 1)
@unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
def testParentDestructorMultipleChildren(self):
diff --git a/sources/shiboken6/tests/samplebinding/ownership_invalidate_after_use_test.py b/sources/shiboken6/tests/samplebinding/ownership_invalidate_after_use_test.py
index e51b5555f..37b7591e4 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_invalidate_after_use_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_invalidate_after_use_test.py
@@ -21,11 +21,13 @@ class ExtObjectType(ObjectType):
ObjectType.__init__(self)
self.type_of_last_event = None
self.last_event = None
+
def event(self, event):
self.last_event = event
self.type_of_last_event = event.eventType()
return True
+
class MyObjectType (ObjectType):
def __init__(self):
super(MyObjectType, self).__init__()
@@ -35,7 +37,7 @@ class MyObjectType (ObjectType):
self.callInvalidateEvent(ev)
try:
ev.eventType()
- except:
+ except: # noqa: E722
self.fail = True
raise
return True
@@ -43,21 +45,25 @@ class MyObjectType (ObjectType):
def invalidateEvent(self, ev):
pass
+
class ExtObjectTypeDerived(ObjectTypeDerived):
def __init__(self):
ObjectTypeDerived.__init__(self)
self.type_of_last_event = None
self.last_event = None
+
def event(self, event):
self.last_event = event
self.type_of_last_event = event.eventType()
return True
+
class OwnershipInvalidateAfterUseTest(unittest.TestCase):
'''Ownership tests for cases of invalidation of Python wrapper after use.'''
def testInvalidateAfterUse(self):
- '''In ObjectType.event(Event*) the wrapper object created for Event must me marked as invalid after the method is called.'''
+ '''In ObjectType.event(Event*) the wrapper object created for Event
+ must me marked as invalid after the method is called.'''
eot = ExtObjectType()
eot.causeEvent(Event.SOME_EVENT)
self.assertEqual(eot.type_of_last_event, Event.SOME_EVENT)
@@ -84,6 +90,6 @@ class OwnershipInvalidateAfterUseTest(unittest.TestCase):
self.assertEqual(eot.type_of_last_event, Event.SOME_EVENT)
self.assertRaises(RuntimeError, eot.last_event.eventType)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_invalidate_child_test.py b/sources/shiboken6/tests/samplebinding/ownership_invalidate_child_test.py
index 868c85931..77b7c576c 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_invalidate_child_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_invalidate_child_test.py
@@ -49,6 +49,6 @@ class InvalidateChildTest(unittest.TestCase):
self.assertEqual(child1.objectName(), 'child1')
self.assertRaises(RuntimeError, child2.objectName)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py b/sources/shiboken6/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py
index 66d6ed5d2..8cbefc30c 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Point, BlackBox
+
class OwnershipInvalidateNonPolymorphicTest(unittest.TestCase):
'''The BlackBox class has cases of ownership transference between Python and C++.'''
@@ -27,6 +28,6 @@ class OwnershipInvalidateNonPolymorphicTest(unittest.TestCase):
p1_ret = bb.retrievePoint(p1_ticket)
self.assertEqual(p1_ret, Point(10, 20))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_invalidate_parent_test.py b/sources/shiboken6/tests/samplebinding/ownership_invalidate_parent_test.py
index 82ecafa7d..c721a212c 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_invalidate_parent_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_invalidate_parent_test.py
@@ -34,7 +34,7 @@ class InvalidateParentTest(unittest.TestCase):
grandchild2.setParent(child2)
bbox = BlackBox()
- bbox.keepObjectType(parent) # Should invalidate the parent
+ bbox.keepObjectType(parent) # Should invalidate the parent
self.assertRaises(RuntimeError, parent.objectName)
# some children still valid they are wrapper classes
@@ -43,6 +43,6 @@ class InvalidateParentTest(unittest.TestCase):
self.assertEqual(grandchild1.objectName(), "grandchild1")
self.assertRaises(RuntimeError, grandchild2.objectName)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_reparenting_test.py b/sources/shiboken6/tests/samplebinding/ownership_reparenting_test.py
index acacbf461..304223063 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_reparenting_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_reparenting_test.py
@@ -16,6 +16,7 @@ import sys
from sample import ObjectType
+
class ExtObjectType(ObjectType):
def __init__(self):
ObjectType.__init__(self)
@@ -108,4 +109,3 @@ class ReparentingTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/ownership_transference_test.py b/sources/shiboken6/tests/samplebinding/ownership_transference_test.py
index d1eccb4f6..0e9f08b72 100644
--- a/sources/shiboken6/tests/samplebinding/ownership_transference_test.py
+++ b/sources/shiboken6/tests/samplebinding/ownership_transference_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import ObjectType, BlackBox
+
class BlackBoxTest(unittest.TestCase):
'''The BlackBox class has cases of ownership transference between C++ and Python.'''
@@ -29,12 +30,13 @@ class BlackBoxTest(unittest.TestCase):
o2.setObjectName('object2')
o2_refcnt = sys.getrefcount(o2)
bb = BlackBox()
- o1_ticket = bb.keepObjectType(o1)
+ o1_ticket = bb.keepObjectType(o1) # noqa: F841
o2_ticket = bb.keepObjectType(o2)
self.assertEqual(set(bb.objects()), set([o1, o2]))
self.assertEqual(str(o1.objectName()), 'object1')
self.assertEqual(str(o2.objectName()), 'object2')
- self.assertEqual(sys.getrefcount(o1), o1_refcnt + 1) # PySide give +1 ref to object with c++ ownership
+ # PySide give +1 ref to object with c++ ownership
+ self.assertEqual(sys.getrefcount(o1), o1_refcnt + 1)
self.assertEqual(sys.getrefcount(o2), o2_refcnt + 1)
o2 = bb.retrieveObjectType(o2_ticket)
self.assertEqual(sys.getrefcount(o2), o2_refcnt)
@@ -48,9 +50,9 @@ class BlackBoxTest(unittest.TestCase):
def testBlackBoxReleasingUnknownObjectType(self):
'''Asks BlackBox to release an unknown ObjectType.'''
o1 = ObjectType()
- o2 = ObjectType()
+ o2 = ObjectType() # noqa: F841
bb = BlackBox()
- o1_ticket = bb.keepObjectType(o1)
+ o1_ticket = bb.keepObjectType(o1) # noqa: F841
o3 = bb.retrieveObjectType(-5)
self.assertEqual(o3, None)
@@ -59,11 +61,11 @@ class BlackBoxTest(unittest.TestCase):
'''Ownership transference using a C++ created object.'''
o1 = ObjectType.create()
o1.setObjectName('object1')
- o1_refcnt = sys.getrefcount(o1)
+ o1_refcnt = sys.getrefcount(o1) # noqa: F841
bb = BlackBox()
- o1_ticket = bb.keepObjectType(o1)
+ o1_ticket = bb.keepObjectType(o1) # noqa: F841
self.assertRaises(RuntimeError, o1.objectName)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/pair_test.py b/sources/shiboken6/tests/samplebinding/pair_test.py
index 278219434..4bd5c697c 100644
--- a/sources/shiboken6/tests/samplebinding/pair_test.py
+++ b/sources/shiboken6/tests/samplebinding/pair_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import PairUser
+
class ExtendedPairUser(PairUser):
def __init__(self):
PairUser.__init__(self)
@@ -24,6 +25,7 @@ class ExtendedPairUser(PairUser):
self.create_pair_called = True
return (7, 13)
+
class PairConversionTest(unittest.TestCase):
'''Test case for std::pair container conversions'''
@@ -48,14 +50,16 @@ class PairConversionTest(unittest.TestCase):
self.assertEqual(cp, (cpx0, cpx1))
def testSumPair(self):
- '''Test method that sums the items of a pair using values of the types expected by C++ (int and double)'''
+ '''Test method that sums the items of a pair using values of the types
+ expected by C++ (int and double)'''
pu = PairUser()
pair = (3, 7.13)
result = pu.sumPair(pair)
self.assertEqual(result, sum(pair))
def testSumPairDifferentTypes(self):
- '''Test method that sums the items of a pair using values of types different from the ones expected by C++ (int and double)'''
+ '''Test method that sums the items of a pair using values of types different
+ from the ones expected by C++ (int and double)'''
pu = PairUser()
pair = (3.3, 7)
result = pu.sumPair(pair)
@@ -71,7 +75,8 @@ class PairConversionTest(unittest.TestCase):
self.assertEqual(result, pair)
def testConversionInBothDirectionsWithSimilarContainer(self):
- '''Test converting a list, instead of the expected tuple, from Python to C++ and the other way around.'''
+ '''Test converting a list, instead of the expected tuple, from Python to C++
+ and the other way around.'''
pu = PairUser()
pair = [3, 5]
pu.setPair(pair)
@@ -79,6 +84,6 @@ class PairConversionTest(unittest.TestCase):
self.assertNotEqual(result, pair)
self.assertEqual(result, tuple(pair))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/pen_test.py b/sources/shiboken6/tests/samplebinding/pen_test.py
index 88684dc38..106f3bd61 100644
--- a/sources/shiboken6/tests/samplebinding/pen_test.py
+++ b/sources/shiboken6/tests/samplebinding/pen_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Color, Pen, SampleNamespace
+
class TestPen(unittest.TestCase):
'''Simple test case for Pen.'''
diff --git a/sources/shiboken6/tests/samplebinding/point_test.py b/sources/shiboken6/tests/samplebinding/point_test.py
index 5e7415395..f86c0f423 100644
--- a/sources/shiboken6/tests/samplebinding/point_test.py
+++ b/sources/shiboken6/tests/samplebinding/point_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Point
+
class PointTest(unittest.TestCase):
'''Test case for Point class, including operator overloads.'''
@@ -92,5 +93,6 @@ class PointTest(unittest.TestCase):
expected = Point((pt1.x() + pt2.x()) / 2.0, (pt1.y() + pt2.y()) / 2.0)
self.assertEqual(pt1.midpoint(pt2), expected)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/pointerholder_test.py b/sources/shiboken6/tests/samplebinding/pointerholder_test.py
index be2faa118..633525a9c 100644
--- a/sources/shiboken6/tests/samplebinding/pointerholder_test.py
+++ b/sources/shiboken6/tests/samplebinding/pointerholder_test.py
@@ -15,8 +15,10 @@ init_paths()
from sample import PointerHolder
+
class TestPointerHolder(unittest.TestCase):
- '''Test cases for a class that holds an arbitraty pointer and is modified to hold an PyObject.'''
+ '''Test cases for a class that holds an arbitraty pointer and
+ is modified to hold an PyObject.'''
def testStoringAndRetrievingPointer(self):
ph = PointerHolder('Hello')
@@ -31,9 +33,9 @@ class TestPointerHolder(unittest.TestCase):
a = (1, 2, 3)
refcnt = sys.getrefcount(a)
ph = PointerHolder(a)
- ptr = ph.pointer()
+ ptr = ph.pointer() # noqa: F841
self.assertEqual(sys.getrefcount(a), refcnt + 1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/pointerprimitivetype_test.py b/sources/shiboken6/tests/samplebinding/pointerprimitivetype_test.py
index 41a9774e3..4da1a89c6 100644
--- a/sources/shiboken6/tests/samplebinding/pointerprimitivetype_test.py
+++ b/sources/shiboken6/tests/samplebinding/pointerprimitivetype_test.py
@@ -27,8 +27,6 @@ from shiboken_paths import init_paths
init_paths()
from sample import IntArray2, VirtualMethods
-import shiboken6
-_init_pyside_extension() # trigger init, which does not happen in tests
from shibokensupport.signature import get_signature
import typing
@@ -39,7 +37,7 @@ class PointerPrimitiveTypeTest(unittest.TestCase):
def testArraySignature(self):
# signature="IntArray2(const int*)"
found = False
- for sig in IntArray2.__signature__:
+ for sig in get_signature(IntArray2):
if "data" in sig.parameters:
found = True
break
diff --git a/sources/shiboken6/tests/samplebinding/pointf_test.py b/sources/shiboken6/tests/samplebinding/pointf_test.py
index 53616aecb..91c58eb1d 100644
--- a/sources/shiboken6/tests/samplebinding/pointf_test.py
+++ b/sources/shiboken6/tests/samplebinding/pointf_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import PointF
+
class PointFTest(unittest.TestCase):
'''Test case for PointF class, including operator overloads.'''
@@ -45,5 +46,6 @@ class PointFTest(unittest.TestCase):
expected = PointF((pt1.x() + pt2.x()) / 2.0, (pt1.y() + pt2.y()) / 2.0)
self.assertEqual(pt1.midpoint(pt2), expected)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/primitivereferenceargument_test.py b/sources/shiboken6/tests/samplebinding/primitivereferenceargument_test.py
index 45cf534a6..0b9fe2249 100644
--- a/sources/shiboken6/tests/samplebinding/primitivereferenceargument_test.py
+++ b/sources/shiboken6/tests/samplebinding/primitivereferenceargument_test.py
@@ -12,12 +12,17 @@ from shiboken_paths import init_paths
init_paths()
import sample
+
class PrimitiveReferenceArgumentTest(unittest.TestCase):
def testIntReferenceArgument(self):
'''C++ signature: int acceptIntReference(int&)'''
self.assertEqual(sample.acceptIntReference(123), 123)
+ def testIntReturnPtr(self):
+ '''C++ signature: const int *acceptIntReturnPtr(int x)'''
+ self.assertEqual(sample.acceptIntReturnPtr(123), 123)
+
def testOddBoolReferenceArgument(self):
'''C++ signature: OddBool acceptOddBoolReference(OddBool&)'''
self.assertEqual(sample.acceptOddBoolReference(True), True)
@@ -25,5 +30,6 @@ class PrimitiveReferenceArgumentTest(unittest.TestCase):
self.assertNotEqual(sample.acceptOddBoolReference(True), False)
self.assertNotEqual(sample.acceptOddBoolReference(False), True)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/privatector_test.py b/sources/shiboken6/tests/samplebinding/privatector_test.py
index 235882997..63040388d 100644
--- a/sources/shiboken6/tests/samplebinding/privatector_test.py
+++ b/sources/shiboken6/tests/samplebinding/privatector_test.py
@@ -64,6 +64,6 @@ class PrivateCtorTest(unittest.TestCase):
self.assertEqual(pd3.instanceCalls(), calls + 2)
self.assertEqual(sys.getrefcount(pd3), refcnt)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/privatedtor_test.py b/sources/shiboken6/tests/samplebinding/privatedtor_test.py
index 777a9923b..651f63b15 100644
--- a/sources/shiboken6/tests/samplebinding/privatedtor_test.py
+++ b/sources/shiboken6/tests/samplebinding/privatedtor_test.py
@@ -80,6 +80,6 @@ class PrivateDtorTest(unittest.TestCase):
self.assertLess(abs(before - after), 5)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/protected_test.py b/sources/shiboken6/tests/samplebinding/protected_test.py
index 9538125f5..e4ccf721d 100644
--- a/sources/shiboken6/tests/samplebinding/protected_test.py
+++ b/sources/shiboken6/tests/samplebinding/protected_test.py
@@ -16,42 +16,51 @@ init_paths()
from sample import cacheSize
from sample import ProtectedNonPolymorphic, ProtectedVirtualDestructor
-from sample import ProtectedPolymorphic, ProtectedPolymorphicDaughter, ProtectedPolymorphicGrandDaughter
+from sample import (ProtectedPolymorphic, ProtectedPolymorphicDaughter,
+ ProtectedPolymorphicGrandDaughter)
from sample import createProtectedProperty, ProtectedProperty, ProtectedEnumClass
from sample import PrivateDtor
from sample import Event, ObjectType, Point
+
class ExtendedProtectedPolymorphic(ProtectedPolymorphic):
def __init__(self, name):
ProtectedPolymorphic.__init__(self, name)
self.protectedName_called = False
+
def protectedName(self):
self.protectedName_called = True
self._name = 'Extended' + ProtectedPolymorphic.protectedName(self)
return self._name
+
class ExtendedProtectedPolymorphicDaughter(ProtectedPolymorphicDaughter):
def __init__(self, name):
self.protectedName_called = False
ProtectedPolymorphicDaughter.__init__(self, name)
+
def protectedName(self):
self.protectedName_called = True
self._name = 'ExtendedDaughter' + ProtectedPolymorphicDaughter.protectedName(self)
return self._name
+
class ExtendedProtectedPolymorphicGrandDaughter(ProtectedPolymorphicGrandDaughter):
def __init__(self, name):
self.protectedName_called = False
ProtectedPolymorphicGrandDaughter.__init__(self, name)
+
def protectedName(self):
self.protectedName_called = True
self._name = 'ExtendedGrandDaughter' + ProtectedPolymorphicGrandDaughter.protectedName(self)
return self._name
+
class ExtendedProtectedVirtualDestructor(ProtectedVirtualDestructor):
def __init__(self):
ProtectedVirtualDestructor.__init__(self)
+
class ProtectedNonPolymorphicTest(unittest.TestCase):
'''Test cases for protected method in a class without virtual methods.'''
@@ -81,6 +90,7 @@ class ProtectedNonPolymorphicTest(unittest.TestCase):
self.assertEqual(p.dataTypeName(1), 'integer')
self.assertEqual(p.dataTypeName(Point(1, 2)), 'pointer')
+
class ProtectedPolymorphicTest(unittest.TestCase):
'''Test cases for protected method in a class with virtual methods.'''
@@ -110,6 +120,8 @@ class ProtectedPolymorphicTest(unittest.TestCase):
self.assertTrue(p.protectedName_called)
self.assertEqual(p.protectedName(), name)
self.assertEqual(ProtectedPolymorphic.protectedName(p), original_name)
+
+
class ProtectedPolymorphicDaugherTest(unittest.TestCase):
'''Test cases for protected method in a class inheriting for a class with virtual methods.'''
@@ -153,6 +165,7 @@ class ProtectedPolymorphicGrandDaugherTest(unittest.TestCase):
self.assertEqual(p.protectedName(), name)
self.assertEqual(ProtectedPolymorphicGrandDaughter.protectedName(p), original_name)
+
class ProtectedVirtualDtorTest(unittest.TestCase):
'''Test cases for protected virtual destructor.'''
@@ -200,15 +213,18 @@ class ProtectedVirtualDtorTest(unittest.TestCase):
class ExtendedProtectedEnumClass(ProtectedEnumClass):
def __init__(self):
ProtectedEnumClass.__init__(self)
+
def protectedEnumMethod(self, value):
if value == ProtectedEnumClass.ProtectedItem0:
return ProtectedEnumClass.ProtectedItem1
return ProtectedEnumClass.ProtectedItem0
+
def publicEnumMethod(self, value):
if value == ProtectedEnumClass.PublicItem0:
return ProtectedEnumClass.PublicItem1
return ProtectedEnumClass.PublicItem0
+
class ProtectedEnumTest(unittest.TestCase):
'''Test cases for protected enum.'''
@@ -223,47 +239,66 @@ class ProtectedEnumTest(unittest.TestCase):
self.assertEqual(type(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedEnum)
- self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem0)
- self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem1)
-
- self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem0)
- self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem1)
+ self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem0),
+ ProtectedEnumClass.ProtectedItem0)
+ self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem1),
+ ProtectedEnumClass.ProtectedItem1)
+ self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0),
+ ProtectedEnumClass.ProtectedItem0)
+ self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1),
+ ProtectedEnumClass.ProtectedItem1)
def testProtectedMethodWithPublicEnumArgument(self):
'''Calls protected method with public enum argument.'''
obj = ProtectedEnumClass()
- self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
- self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0),
+ ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1),
+ ProtectedEnumClass.PublicItem1)
- self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
- self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0),
+ ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1),
+ ProtectedEnumClass.PublicItem1)
def testOverriddenProtectedMethodWithProtectedEnumArgument(self):
'''Calls overridden protected method with protected enum argument.'''
obj = ExtendedProtectedEnumClass()
- self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem1)
- self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem0)
+ self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem0),
+ ProtectedEnumClass.ProtectedItem1)
+ self.assertEqual(obj.protectedEnumMethod(ProtectedEnumClass.ProtectedItem1),
+ ProtectedEnumClass.ProtectedItem0)
- self.assertEqual(ProtectedEnumClass.protectedEnumMethod(obj, ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem0)
- self.assertEqual(ProtectedEnumClass.protectedEnumMethod(obj, ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem1)
+ self.assertEqual(ProtectedEnumClass.protectedEnumMethod(obj, ProtectedEnumClass.ProtectedItem0), # noqa: E501
+ ProtectedEnumClass.ProtectedItem0)
+ self.assertEqual(ProtectedEnumClass.protectedEnumMethod(obj,
+ ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem1)
- self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0), ProtectedEnumClass.ProtectedItem1)
- self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1), ProtectedEnumClass.ProtectedItem0)
+ self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem0),
+ ProtectedEnumClass.ProtectedItem1)
+ self.assertEqual(obj.callProtectedEnumMethod(ProtectedEnumClass.ProtectedItem1),
+ ProtectedEnumClass.ProtectedItem0)
def testOverriddenProtectedMethodWithPublicEnumArgument(self):
'''Calls overridden protected method with public enum argument.'''
obj = ExtendedProtectedEnumClass()
- self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem1)
- self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem0),
+ ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.publicEnumMethod(ProtectedEnumClass.PublicItem1),
+ ProtectedEnumClass.PublicItem0)
- self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem0)
- self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem1)
+ self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem0),
+ ProtectedEnumClass.PublicItem0)
+ self.assertEqual(ProtectedEnumClass.publicEnumMethod(obj, ProtectedEnumClass.PublicItem1),
+ ProtectedEnumClass.PublicItem1)
- self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0), ProtectedEnumClass.PublicItem1)
- self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1), ProtectedEnumClass.PublicItem0)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem0),
+ ProtectedEnumClass.PublicItem1)
+ self.assertEqual(obj.callPublicEnumMethod(ProtectedEnumClass.PublicItem1),
+ ProtectedEnumClass.PublicItem0)
class ProtectedPropertyTest(unittest.TestCase):
@@ -361,6 +396,6 @@ class PrivateDtorProtectedMethodTest(unittest.TestCase):
self.assertEqual(obj.instanceCalls(), 2)
self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls())
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/pstrlist_test.py b/sources/shiboken6/tests/samplebinding/pstrlist_test.py
index a257d5944..d60f9cf35 100644
--- a/sources/shiboken6/tests/samplebinding/pstrlist_test.py
+++ b/sources/shiboken6/tests/samplebinding/pstrlist_test.py
@@ -12,6 +12,7 @@ from shiboken_paths import init_paths
init_paths()
import sample
+
class PStrListTest(unittest.TestCase):
def testPStrList(self):
@@ -26,5 +27,6 @@ class PStrListTest(unittest.TestCase):
lst = sample.createListOfPStr(a, b)
self.assertEqual(lst, [a, b])
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/pystr_test.py b/sources/shiboken6/tests/samplebinding/pystr_test.py
index 3472457e8..ec64c1e31 100644
--- a/sources/shiboken6/tests/samplebinding/pystr_test.py
+++ b/sources/shiboken6/tests/samplebinding/pystr_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Point
+
class PyStrTest(unittest.TestCase):
'''Test case for definition of __str__ method.'''
@@ -23,6 +24,6 @@ class PyStrTest(unittest.TestCase):
pt = Point(5, 2)
self.assertEqual(str(pt), 'Point(5.0, 2.0)')
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/python_thread_test.py b/sources/shiboken6/tests/samplebinding/python_thread_test.py
index 03a75b824..65398b5c6 100644
--- a/sources/shiboken6/tests/samplebinding/python_thread_test.py
+++ b/sources/shiboken6/tests/samplebinding/python_thread_test.py
@@ -36,7 +36,7 @@ class Producer(threading.Thread):
def run(self):
while self.runs < self.max_runs:
- value = int(random()*10) % 10
+ value = int(random() * 10) % 10
self.bucket.push(value)
self.production_list.append(value)
logging.debug(f'PRODUCER - pushed {value}')
@@ -66,6 +66,7 @@ class Consumer(threading.Thread):
logging.debug('CONSUMER - empty bucket')
time.sleep(0.01)
+
class ProducerConsumer(unittest.TestCase):
'''Basic test case for producer-consumer QThread'''
@@ -91,8 +92,5 @@ class ProducerConsumer(unittest.TestCase):
self.assertEqual(prod.production_list, cons.consumption_list)
-
-
-
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/receive_null_cstring_test.py b/sources/shiboken6/tests/samplebinding/receive_null_cstring_test.py
index f8c7f017d..1d19de941 100644
--- a/sources/shiboken6/tests/samplebinding/receive_null_cstring_test.py
+++ b/sources/shiboken6/tests/samplebinding/receive_null_cstring_test.py
@@ -15,8 +15,10 @@ init_paths()
from sample import countCharacters
+
class ReceiveNullCStringTest(unittest.TestCase):
- '''Test case for a function that could receive a NULL pointer in a '[const] char*' parameter.'''
+ '''Test case for a function that could receive a NULL pointer in a '[const] char*'
+ parameter.'''
def testBasic(self):
'''The test function should be working for the basic cases.'''
@@ -29,6 +31,6 @@ class ReceiveNullCStringTest(unittest.TestCase):
'''The test function returns '-1' when receives a None value instead of a string.'''
self.assertEqual(countCharacters(None), -1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/reference_test.py b/sources/shiboken6/tests/samplebinding/reference_test.py
index e590a7e4e..1b6dd3a7a 100644
--- a/sources/shiboken6/tests/samplebinding/reference_test.py
+++ b/sources/shiboken6/tests/samplebinding/reference_test.py
@@ -13,7 +13,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Reference, Str
+
class ExtendedReference(Reference):
def __init__(self):
@@ -48,7 +49,7 @@ class ReferenceTest(unittest.TestCase):
def testCantSegFaultWhenReceiveNone(self):
'''do not segfault when receiving None as argument.'''
s = Str()
- self.assertTrue(None == s)
+ self.assertFalse(bool(s))
def testMethodThatReceivesConstReference(self):
'''Test a method that receives a const reference to an object as argument.'''
@@ -57,29 +58,33 @@ class ReferenceTest(unittest.TestCase):
self.assertEqual(Reference.usesConstReference(r), objId)
def testModificationOfReference(self):
- '''Tests if the identity of a reference argument is preserved when passing it to be altered in C++.'''
+ '''Tests if the identity of a reference argument is preserved when passing
+ it to be altered in C++.'''
objId = 123
r1 = Reference(objId)
r1.alterReferenceIdVirtual(r1)
self.assertEqual(r1.objId(), objId * Reference.multiplier())
def testModificationOfReferenceCallingAVirtualIndirectly(self):
- '''Tests if the identity of a reference argument is preserved when passing it to be altered in C++ through a method that calls a virtual method.'''
+ '''Tests if the identity of a reference argument is preserved when passing it
+ to be altered in C++ through a method that calls a virtual method.'''
objId = 123
r1 = Reference(objId)
r1.callAlterReferenceIdVirtual(r1)
self.assertEqual(r1.objId(), objId * Reference.multiplier())
def testModificationOfReferenceCallingAReimplementedVirtualIndirectly(self):
- '''Test if a Python override of a virtual method with a reference parameter called from C++ alters the argument properly.'''
+ '''Test if a Python override of a virtual method with a reference parameter
+ called from C++ alters the argument properly.'''
objId = 123
r = Reference(objId)
er = ExtendedReference()
- result = er.callAlterReferenceIdVirtual(r)
+ result = er.callAlterReferenceIdVirtual(r) # noqa: F841
self.assertEqual(r.objId(), objId * er.multiplier)
def testReimplementedVirtualMethodCallWithReferenceParameter(self):
- '''Test if a Python override of a virtual method with a reference parameter is correctly called from C++.'''
+ '''Test if a Python override of a virtual method with a reference parameter
+ is correctly called from C++.'''
inc = 9
objId = 123
r = Reference(objId)
@@ -88,7 +93,8 @@ class ReferenceTest(unittest.TestCase):
self.assertEqual(result, objId + inc + er.reference_inc)
def testReimplementedVirtualMethodCallWithConstReferenceParameter(self):
- '''Test if a Python override of a virtual method with a const reference parameter is correctly called from C++.'''
+ '''Test if a Python override of a virtual method with a const reference
+ parameter is correctly called from C++.'''
inc = 9
objId = 123
r = Reference(objId)
@@ -96,6 +102,6 @@ class ReferenceTest(unittest.TestCase):
result = er.callUsesConstReferenceVirtual(r, inc)
self.assertEqual(result, objId + inc + er.const_reference_inc)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/referencetopointer_test.py b/sources/shiboken6/tests/samplebinding/referencetopointer_test.py
index 94bb1608b..942c7ea29 100644
--- a/sources/shiboken6/tests/samplebinding/referencetopointer_test.py
+++ b/sources/shiboken6/tests/samplebinding/referencetopointer_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import VirtualMethods, Str
+
class ExtendedVirtualMethods(VirtualMethods):
def __init__(self):
VirtualMethods.__init__(self)
@@ -72,6 +73,6 @@ class ReferenceToPointerTest(unittest.TestCase):
self.assertTrue(ok)
self.assertEqual(string, Str(obj.prefix + 'foo'))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/renaming_test.py b/sources/shiboken6/tests/samplebinding/renaming_test.py
index 2d6b95a45..b08438ef3 100644
--- a/sources/shiboken6/tests/samplebinding/renaming_test.py
+++ b/sources/shiboken6/tests/samplebinding/renaming_test.py
@@ -16,9 +16,6 @@ init_paths()
from sample import RenamedValue, RenamedUser
-from shiboken6 import Shiboken
-_init_pyside_extension() # trigger bootstrap
-
from shibokensupport.signature import get_signature
@@ -38,6 +35,5 @@ class RenamingTest(unittest.TestCase):
actual_signature))
-
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/return_null_test.py b/sources/shiboken6/tests/samplebinding/return_null_test.py
index 46d19e9f7..2c4f07c65 100644
--- a/sources/shiboken6/tests/samplebinding/return_null_test.py
+++ b/sources/shiboken6/tests/samplebinding/return_null_test.py
@@ -13,7 +13,9 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import returnNullPrimitivePointer, returnNullValueTypePointer, returnNullObjectTypePointer
+from sample import (returnNullPrimitivePointer, returnNullValueTypePointer,
+ returnNullObjectTypePointer)
+
class ReturnNullTest(unittest.TestCase):
'''Test case for functions that could return a NULL pointer.'''
@@ -33,6 +35,6 @@ class ReturnNullTest(unittest.TestCase):
o = returnNullValueTypePointer()
self.assertEqual(o, None)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/richcompare_test.py b/sources/shiboken6/tests/samplebinding/richcompare_test.py
index e764b41a4..3146d0faf 100644
--- a/sources/shiboken6/tests/samplebinding/richcompare_test.py
+++ b/sources/shiboken6/tests/samplebinding/richcompare_test.py
@@ -11,7 +11,8 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Expression
+
class TestRichCompare(unittest.TestCase):
@@ -22,5 +23,6 @@ class TestRichCompare(unittest.TestCase):
d = a + c < b + a
self.assertEqual(d.toString(), "((2+(2+3))<(3+2))")
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/sample-binding.txt.in b/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
index 317f76f09..bcf9de90f 100644
--- a/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
+++ b/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers
diff --git a/sources/shiboken6/tests/samplebinding/sample_test.py b/sources/shiboken6/tests/samplebinding/sample_test.py
index 52abc968f..19b2f708d 100644
--- a/sources/shiboken6/tests/samplebinding/sample_test.py
+++ b/sources/shiboken6/tests/samplebinding/sample_test.py
@@ -15,35 +15,10 @@ init_paths()
import sample
+
class ModuleTest(unittest.TestCase):
'''Test case for module and global functions'''
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testModuleMembers(self):
- '''Test availability of classes, global functions and other members on binding'''
- expected_members = set(['Abstract', 'Derived', 'Point',
- 'ListUser', 'PairUser', 'MapUser',
- 'gimmeComplexList', 'gimmeDouble', 'gimmeInt',
- 'makeCString', 'multiplyPair', 'returnCString',
- 'SampleNamespace', 'transmuteComplexIntoPoint',
- 'transmutePointIntoComplex', 'sumComplexPair',
- 'FirstThing', 'SecondThing', 'ThirdThing',
- 'GlobalEnum', 'NoThing'])
- self.assertTrue(expected_members.issubset(dir(sample)))
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testAbstractPrintFormatEnum(self):
- '''Test availability of PrintFormat enum from Abstract class'''
- enum_members = set(['PrintFormat', 'Short', 'Verbose',
- 'OnlyId', 'ClassNameAndId'])
- self.assertTrue(enum_members.issubset(dir(sample.Abstract)))
-
- @unittest.skipIf(sys.pyside63_option_python_enum, "Makes no sense with strict Enums")
- def testSampleNamespaceOptionEnum(self):
- '''Test availability of Option enum from SampleNamespace namespace'''
- enum_members = set(['Option', 'None_', 'RandomNumber', 'UnixTime'])
- self.assertTrue(enum_members.issubset(dir(sample.SampleNamespace)))
-
def testAddedFunctionAtModuleLevel(self):
'''Calls function added to module from type system description.'''
str1 = 'Foo'
@@ -76,7 +51,26 @@ class ModuleTest(unittest.TestCase):
sample.testNullPtrT(None)
self.assertRaises(TypeError, sample.testNullPtrT, 42)
+ def testRValueRefsWithValueTypes(self):
+ """Passing value types by rvalue refs: For value types, nothing should
+ happen since the argument is copied in the call and the copy is
+ moved from."""
+ polygon = sample.Polygon()
+ polygon.addPoint(sample.Point(1, 2))
+ polygon.addPoint(sample.Point(3, 4))
+ point_count = len(polygon.points())
+ self.assertEqual(point_count, sample.takePolygon(polygon))
+
+ def testRValueRefsWithObjectTypes(self):
+ """Passing object types by rvalue refs: The underlying object should
+ be moved from."""
+ o = sample.ObjectType()
+ object_name = "Name"
+ o.setObjectName(object_name)
+ self.assertEqual(len(object_name), sample.takeObjectType(o))
+ # o should be moved from, name is now empty
+ self.assertEqual(len(o.objectName()), 0)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/samplebinding.pyproject b/sources/shiboken6/tests/samplebinding/samplebinding.pyproject
new file mode 100644
index 000000000..ba6ba6f8f
--- /dev/null
+++ b/sources/shiboken6/tests/samplebinding/samplebinding.pyproject
@@ -0,0 +1,131 @@
+{
+ "files": ["__del___test.py",
+ "abstract_test.py",
+ "addedfunction_test.py",
+ "addedfunction_with_container_args_test.py",
+ "argumentmodifications_test.py",
+ "array_numpy_test.py",
+ "array_sequence_test.py",
+ "bug_554_test.py",
+ "bug_704_test.py",
+ "bytearray_test.py",
+ "child_return_test.py",
+ "class_fields_test.py",
+ "collector_test.py",
+ "complex_test.py",
+ "conversion_operator_test.py",
+ "copy_test.py",
+ "ctorconvrule_test.py",
+ "cyclic_test.py",
+ "date_test.py",
+ "decisor_test.py",
+ "delete_test.py",
+ "deprecated_test.py",
+ "derived_test.py",
+ "duck_punching_test.py",
+ "echo_test.py",
+ "enum_test.py",
+ "enumfromremovednamespace_test.py",
+ "event_loop_call_virtual_test.py",
+ "event_loop_thread_test.py",
+ "exception_test.py",
+ "filter_test.py",
+ "handleholder_test.py",
+ "hashabletype_test.py",
+ "ignorederefop_test.py",
+ "implicitconv_numerical_test.py",
+ "implicitconv_test.py",
+ "inheritanceandscope_test.py",
+ "injectcode_test.py",
+ "innerclass_test.py",
+ "intlist_test.py",
+ "intwrapper_test.py",
+ "invalid_virtual_return_test.py",
+ "keep_reference_test.py",
+ "list_test.py",
+ "lock_test.py",
+ "map_test.py",
+ "metaclass_test.py",
+ "mi_virtual_methods_test.py",
+ "mixed_mi_test.py",
+ "modelindex_test.py",
+ "modelview_test.py",
+ "modifications_test.py",
+ "modified_constructor_test.py",
+ "modifiedvirtualmethods_test.py",
+ "multi_cpp_inheritance_test.py",
+ "multiple_derived_test.py",
+ "namespace_test.py",
+ "newdivision_test.py",
+ "nondefaultctor_test.py",
+ "nontypetemplate_test.py",
+ "nonzero_test.py",
+ "numericaltypedef_test.py",
+ "numpy_test.py",
+ "objecttype_test.py",
+ "objecttype_with_named_args_test.py",
+ "objecttypebyvalue_test.py",
+ "objecttypelayout_test.py",
+ "objecttypeoperators_test.py",
+ "objecttypereferenceasvirtualmethodargument_test.py",
+ "oddbool_test.py",
+ "onlycopyclass_test.py",
+ "overflow_test.py",
+ "overload_sorting_test.py",
+ "overload_test.py",
+ "overloadwithdefault_test.py",
+ "ownership_argument_invalidation_test.py",
+ "ownership_delete_child_in_cpp_test.py",
+ "ownership_delete_child_in_python_test.py",
+ "ownership_delete_parent_test.py",
+ "ownership_invalidate_after_use_test.py",
+ "ownership_invalidate_child_test.py",
+ "ownership_invalidate_nonpolymorphic_test.py",
+ "ownership_invalidate_parent_test.py",
+ "ownership_reparenting_test.py",
+ "ownership_transference_test.py",
+ "pair_test.py",
+ "pen_test.py",
+ "point_test.py",
+ "pointerholder_test.py",
+ "pointerprimitivetype_test.py",
+ "pointf_test.py",
+ "primitivereferenceargument_test.py",
+ "privatector_test.py",
+ "privatedtor_test.py",
+ "protected_test.py",
+ "pstrlist_test.py",
+ "pystr_test.py",
+ "python_thread_test.py",
+ "receive_null_cstring_test.py",
+ "reference_test.py",
+ "referencetopointer_test.py",
+ "renaming_test.py",
+ "return_null_test.py",
+ "richcompare_test.py",
+ "sample_test.py",
+ "samplesnippets.cpp",
+ "simplefile_glue.cpp",
+ "simplefile_test.py",
+ "size_test.py",
+ "snakecase_test.py",
+ "static_nonstatic_methods_test.py",
+ "str_test.py",
+ "strlist_test.py",
+ "templateinheritingclass_test.py",
+ "time_test.py",
+ "transform_test.py",
+ "typeconverters_test.py",
+ "typedealloc_test.py",
+ "typedtordoublefree_test.py",
+ "typesystypedef_test.py",
+ "unsafe_parent_test.py",
+ "useraddedctor_test.py",
+ "virtualdtor_test.py",
+ "virtualmethods_test.py",
+ "visibilitychange_test.py",
+ "voidholder_test.py",
+ "weakref_test.py",
+ "writableclassdict_test.py",
+ "typesystem_sample.xml"]
+}
diff --git a/sources/shiboken6/tests/samplebinding/samplesnippets.cpp b/sources/shiboken6/tests/samplebinding/samplesnippets.cpp
index e71ba3737..43e6b08de 100644
--- a/sources/shiboken6/tests/samplebinding/samplesnippets.cpp
+++ b/sources/shiboken6/tests/samplebinding/samplesnippets.cpp
@@ -3,7 +3,7 @@
// @snippet intwrapper_add_ints
extern "C" {
-static PyObject *Sbk_IntWrapper_add_ints(PyObject *self, PyObject *args)
+static PyObject *Sbk_IntWrapper_add_ints(PyObject * /* self */, PyObject *args)
{
PyObject *result = nullptr;
if (PyTuple_Check(args) != 0 && PyTuple_Size(args) == 2) {
@@ -18,3 +18,37 @@ static PyObject *Sbk_IntWrapper_add_ints(PyObject *self, PyObject *args)
}
}
// @snippet intwrapper_add_ints
+
+// @snippet stdcomplex_floor
+%PYARG_0 = PyFloat_FromDouble(std::floor(%CPPSELF.abs_value()));
+// @snippet stdcomplex_floor
+
+// @snippet stdcomplex_ceil
+%PYARG_0 = PyFloat_FromDouble(std::ceil(%CPPSELF.abs_value()));
+// @snippet stdcomplex_ceil
+
+// @snippet stdcomplex_abs
+%PYARG_0 = PyFloat_FromDouble(%CPPSELF.abs_value());
+// @snippet stdcomplex_abs
+
+// @snippet stdcomplex_pow
+%RETURN_TYPE %0 = %CPPSELF.pow(%1);
+%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+// @snippet stdcomplex_pow
+
+// @snippet size_char_ct
+// Convert a string "{width}x{height}" specification
+{
+ double width = -1;
+ double height = -1;
+ const std::string s = %1;
+ const auto pos = s.find('x');
+ if (pos != std::string::npos) {
+ std::istringstream wstr(s.substr(0, pos));
+ wstr >> width;
+ std::istringstream hstr(s.substr(pos + 1, s.size() - pos - 1));
+ hstr >> height;
+ }
+ %0 = new %TYPE(width, height);
+}
+// @snippet size_char_ct
diff --git a/sources/shiboken6/tests/samplebinding/simplefile_test.py b/sources/shiboken6/tests/samplebinding/simplefile_test.py
index 1217bd9a8..55c894a35 100644
--- a/sources/shiboken6/tests/samplebinding/simplefile_test.py
+++ b/sources/shiboken6/tests/samplebinding/simplefile_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import SimpleFile
+
class SimpleFileTest(unittest.TestCase):
'''Test cases for SimpleFile class.'''
@@ -54,6 +55,6 @@ class SimpleFileTest(unittest.TestCase):
self.assertRaises(IOError, f.open)
self.assertEqual(f.size(), 0)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/size_test.py b/sources/shiboken6/tests/samplebinding/size_test.py
index 179a961d9..069ce59b3 100644
--- a/sources/shiboken6/tests/samplebinding/size_test.py
+++ b/sources/shiboken6/tests/samplebinding/size_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Size
+
class PointTest(unittest.TestCase):
'''Test case for Size class, including operator overloads.'''
@@ -94,6 +95,6 @@ class PointTest(unittest.TestCase):
self.assertTrue(s1 > s2)
self.assertFalse(s2 > s1)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/static_nonstatic_methods_test.py b/sources/shiboken6/tests/samplebinding/static_nonstatic_methods_test.py
index e176b3347..cf0889299 100644
--- a/sources/shiboken6/tests/samplebinding/static_nonstatic_methods_test.py
+++ b/sources/shiboken6/tests/samplebinding/static_nonstatic_methods_test.py
@@ -15,16 +15,20 @@ init_paths()
from sample import SimpleFile
+
class SimpleFile2 (SimpleFile):
def exists(self):
return "Mooo"
+
class SimpleFile3 (SimpleFile):
pass
+
class SimpleFile4 (SimpleFile):
exists = 5
+
class StaticNonStaticMethodsTest(unittest.TestCase):
'''Test cases for overloads involving static and non-static versions of a method.'''
@@ -79,9 +83,9 @@ class StaticNonStaticMethodsTest(unittest.TestCase):
def testDuckPunchingStaticNonStaticMethod(self):
f = SimpleFile(os.fspath(self.existing_filename))
- f.exists = lambda : "Meee"
+ f.exists = lambda: "Meee"
self.assertEqual(f.exists(), "Meee")
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/stdcomplex_test.py b/sources/shiboken6/tests/samplebinding/stdcomplex_test.py
new file mode 100644
index 000000000..0caa9764d
--- /dev/null
+++ b/sources/shiboken6/tests/samplebinding/stdcomplex_test.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+'''Test cases for StdComplex class'''
+
+import os
+import math
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from shiboken_paths import init_paths
+init_paths()
+
+from sample import StdComplex
+
+
+REAL = 5.0
+IMAG = 2.3
+
+
+class StdComplexTest(unittest.TestCase):
+ '''Test case for StdComplex class, exercising esoteric number
+ protocols (Py_nb_). For standard number protocols, see Point.'''
+
+ def testConversion(self):
+ pt = StdComplex(REAL, IMAG)
+ self.assertEqual(int(pt), int(round(pt.abs_value())))
+ self.assertEqual(float(pt), pt.abs_value())
+
+ def testAbs(self):
+ pt = StdComplex(REAL, IMAG)
+ self.assertEqual(abs(pt), pt.abs_value())
+
+ def testPow(self):
+ '''Compare pow() function to builtin Python type.'''
+ pt = StdComplex(REAL, IMAG)
+ result = pow(pt, StdComplex(2.0, 0))
+ py_pt = complex(REAL, IMAG)
+ py_result = pow(py_pt, complex(2.0, 0))
+ self.assertAlmostEqual(result.real(), py_result.real)
+ self.assertAlmostEqual(result.imag(), py_result.imag)
+
+ def testFloor(self):
+ pt = StdComplex(REAL, IMAG)
+ self.assertEqual(math.floor(pt), math.floor(pt.abs_value()))
+
+ def testCeil(self):
+ pt = StdComplex(REAL, IMAG)
+ self.assertEqual(math.ceil(pt), math.ceil(pt.abs_value()))
+
+ def testPlusOperator(self):
+ '''Test StdComplex class + operator.'''
+ pt1 = StdComplex(REAL, IMAG)
+ pt2 = StdComplex(0.5, 3.2)
+ self.assertEqual(pt1 + pt2, StdComplex(REAL + 0.5, IMAG + 3.2))
+
+ def testEqualOperator(self):
+ '''Test StdComplex class == operator.'''
+ pt1 = StdComplex(REAL, IMAG)
+ pt2 = StdComplex(REAL, IMAG)
+ pt3 = StdComplex(0.5, 3.2)
+ self.assertTrue(pt1 == pt1)
+ self.assertTrue(pt1 == pt2)
+ self.assertFalse(pt1 == pt3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/str_test.py b/sources/shiboken6/tests/samplebinding/str_test.py
index 97df76452..c06fd6428 100644
--- a/sources/shiboken6/tests/samplebinding/str_test.py
+++ b/sources/shiboken6/tests/samplebinding/str_test.py
@@ -2,7 +2,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-'''Test cases for a method that receives a reference to class that is implicitly convertible from a Python native type.'''
+'''Test cases for a method that receives a reference to class that is implicitly
+ convertible from a Python native type.'''
import os
import sys
@@ -15,6 +16,7 @@ init_paths()
from sample import Str
+
class StrTest(unittest.TestCase):
'''Test cases for thr Str class.'''
@@ -31,39 +33,39 @@ class StrTest(unittest.TestCase):
self.assertEqual(str(s1), 'This is Sparta!')
def testPassPythonTypeImplictlyConvertibleToAClassUsedAsReference(self):
- '''Test passing a Python class implicitly convertible to a wrapped class that is expected to be passed as reference.'''
+ '''Test passing a Python class implicitly convertible to a wrapped class
+ that is expected to be passed as reference.'''
s1 = Str('This is %VAR!').arg('Athens')
self.assertEqual(str(s1), 'This is Athens!')
def testSequenceOperators(self):
s1 = Str("abcdef")
- self.assertEqual(len(s1), 6);
- self.assertEqual(len(Str()), 0);
+ self.assertEqual(len(s1), 6)
+ self.assertEqual(len(Str()), 0)
# getitem
- self.assertEqual(s1[0], "a");
- self.assertEqual(s1[1], "b");
- self.assertEqual(s1[2], "c");
- self.assertEqual(s1[3], "d");
- self.assertEqual(s1[4], "e");
- self.assertEqual(s1[5], "f");
- self.assertEqual(s1[-1], "f");
- self.assertEqual(s1[-2], "e");
+ self.assertEqual(s1[0], "a")
+ self.assertEqual(s1[1], "b")
+ self.assertEqual(s1[2], "c")
+ self.assertEqual(s1[3], "d")
+ self.assertEqual(s1[4], "e")
+ self.assertEqual(s1[5], "f")
+ self.assertEqual(s1[-1], "f")
+ self.assertEqual(s1[-2], "e")
self.assertRaises(TypeError, s1.__getitem__, 6)
# setitem
s1[0] = 'A'
s1[1] = 'B'
- self.assertEqual(s1[0], 'A');
- self.assertEqual(s1[1], 'B');
+ self.assertEqual(s1[0], 'A')
+ self.assertEqual(s1[1], 'B')
self.assertRaises(TypeError, s1.__setitem__(6, 67))
def testReverseOperator(self):
s1 = Str("hello")
- n1 = 2
- self.assertEqual(s1+2, "hello2")
- self.assertEqual(2+s1, "2hello")
+ self.assertEqual(s1 + 2, "hello2")
+ self.assertEqual(2 + s1, "2hello")
def testToIntError(self):
self.assertEqual(Str('Z').toInt(), (0, False))
@@ -90,6 +92,6 @@ class StrTest(unittest.TestCase):
self.assertEqual(val, int(str(hexa), 16))
self.assertEqual(hexa.toInt(), (0, False))
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/strlist_test.py b/sources/shiboken6/tests/samplebinding/strlist_test.py
index f768f9c63..2bfb80b67 100644
--- a/sources/shiboken6/tests/samplebinding/strlist_test.py
+++ b/sources/shiboken6/tests/samplebinding/strlist_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Str, StrList
+
class StrListTest(unittest.TestCase):
'''Test cases for StrList class that inherits from std::list<Str>.'''
@@ -88,5 +89,6 @@ class StrListTest(unittest.TestCase):
self.assertEqual(len(sl), 2)
self.assertEqual(sl, (Str('Foo'), 'Bar'))
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/templateinheritingclass_test.py b/sources/shiboken6/tests/samplebinding/templateinheritingclass_test.py
index f458ad0d2..11279c7ec 100644
--- a/sources/shiboken6/tests/samplebinding/templateinheritingclass_test.py
+++ b/sources/shiboken6/tests/samplebinding/templateinheritingclass_test.py
@@ -14,7 +14,8 @@ init_paths()
from sample import Photon
'''This tests classes that inherit from template classes,
-simulating a situation found in Qt's phonon module.'''
+ simulating a situation found in Qt's phonon module.'''
+
class TemplateInheritingClassTest(unittest.TestCase):
def testClassBasics(self):
@@ -57,5 +58,6 @@ class TemplateInheritingClassTest(unittest.TestCase):
self.assertEqual(obj2, obj2.passPointerThrough(obj2))
self.assertRaises(TypeError, obj1.passPointerThrough, obj2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/time_test.py b/sources/shiboken6/tests/samplebinding/time_test.py
index 9b32aaaee..6283a6744 100644
--- a/sources/shiboken6/tests/samplebinding/time_test.py
+++ b/sources/shiboken6/tests/samplebinding/time_test.py
@@ -4,7 +4,6 @@
'''Test cases for constructor and method signature decisor on Time class.'''
-import sys
import os
import sys
import unittest
@@ -17,6 +16,7 @@ import datetime
from sample import Time, ImplicitConv, ObjectType
+
class TimeTest(unittest.TestCase):
'''Test cases for constructor and method signature decisor on Time class.
The constructor and one method have these signatures: CTORMETHOD() and
@@ -115,6 +115,6 @@ class TimeTest(unittest.TestCase):
py = datetime.time(12, 32, 5)
self.assertNotEqual(time, py)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/transform_test.py b/sources/shiboken6/tests/samplebinding/transform_test.py
index a938e6af8..7dfd18a4a 100644
--- a/sources/shiboken6/tests/samplebinding/transform_test.py
+++ b/sources/shiboken6/tests/samplebinding/transform_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import Point, applyHomogeneousTransform
+
class TransformTest(unittest.TestCase):
'''Test cases for modifying a function with > 9 arguments.'''
@@ -32,5 +33,6 @@ class TransformTest(unittest.TestCase):
r = applyHomogeneousTransform(p, 1, 0, 0, 0, 1, 0, 0, 0, 0)
self.assertTrue(r is None)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typeconverters_test.py b/sources/shiboken6/tests/samplebinding/typeconverters_test.py
index 10b7491b1..987ba6dfd 100644
--- a/sources/shiboken6/tests/samplebinding/typeconverters_test.py
+++ b/sources/shiboken6/tests/samplebinding/typeconverters_test.py
@@ -15,6 +15,7 @@ init_paths()
import sample
+
class GetPythonTypeByNameTest(unittest.TestCase):
'''Uses an added function with inject code that uses the libshiboken
@@ -159,12 +160,31 @@ class StringBasedConversionTest(unittest.TestCase):
self.assertTrue(len(result), 1)
self.assertTrue(lst, result[0])
+
+class PrimitiveConversionTest(unittest.TestCase):
+
def testCppPrimitiveType(self):
integers = (12, 34)
result = sample.convertIntegersToCppAndThenToPython(integers[0], integers[1])
for orig, new in zip(integers, result):
self.assertEqual(orig, new)
+ def testLargeIntAsFloat(self):
+ """PYSIDE-2417: When passing an int to a function taking float,
+ a 64bit conversion should be done."""
+ point = sample.PointF(1, 2)
+ large_int = 2**31 + 2
+ point.setX(large_int)
+ self.assertEqual(round(point.x()), large_int)
+
+ def testUnsignedLongLongAsFloat(self):
+ """PYSIDE-2652: When passing an unsigned long long to a function taking float,
+ an unsigned 64bit conversion should be done."""
+ point = sample.PointF(1, 2)
+ large_int = 2**63
+ point.setX(large_int)
+ self.assertEqual(round(point.x()), large_int)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typedealloc_test.py b/sources/shiboken6/tests/samplebinding/typedealloc_test.py
index 1b47c62bc..ce881e802 100644
--- a/sources/shiboken6/tests/samplebinding/typedealloc_test.py
+++ b/sources/shiboken6/tests/samplebinding/typedealloc_test.py
@@ -33,12 +33,16 @@ class TypeDeallocTest(unittest.TestCase):
def testScopeEnd(self):
ref = None
+
def scope():
+
class Ext(Point):
pass
- o = Ext()
+
+ o = Ext() # noqa: F841
global ref
ref = weakref.ref(Ext, self.callback)
+
scope()
gc.collect()
self.assertTrue(self.called)
@@ -46,7 +50,7 @@ class TypeDeallocTest(unittest.TestCase):
def testDeleteType(self):
class Ext(Point):
pass
- ref = weakref.ref(Ext, self.callback)
+ ref = weakref.ref(Ext, self.callback) # noqa: F841
del Ext
gc.collect()
self.assertTrue(self.called)
@@ -54,4 +58,3 @@ class TypeDeallocTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/typedtordoublefree_test.py b/sources/shiboken6/tests/samplebinding/typedtordoublefree_test.py
index c486f2bcc..ab8e535b5 100644
--- a/sources/shiboken6/tests/samplebinding/typedtordoublefree_test.py
+++ b/sources/shiboken6/tests/samplebinding/typedtordoublefree_test.py
@@ -12,6 +12,7 @@ from shiboken_paths import init_paths
init_paths()
from sample import ObjectType
+
class TestTypeDestructorDoubleFree(unittest.TestCase):
def testTypeDestructorDoubleFree(self):
'''Causes the type destructors of two derived classes to be called.'''
@@ -22,13 +23,16 @@ class TestTypeDestructorDoubleFree(unittest.TestCase):
obj = ExtObj1()
child = ObjectType(parent=obj)
self.assertEqual(obj.takeChild(child), child)
+
class ExtObj2(ObjectType):
def __init__(self):
ObjectType.__init__(self)
+
obj = ExtObj2()
child = ObjectType(parent=obj)
self.assertEqual(obj.takeChild(child), child)
scope()
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index 7583a900a..e315e599e 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<typesystem package="sample">
- <suppress-warning text="Duplicate type entry: 'sample'" />
- <suppress-warning text="Duplicate type entry: 'SampleNamespace'" />
-
<primitive-type name="ObjectType::Identifier"/>
<primitive-type name="std::nullptr_t"/>
- <primitive-type name="Foo::HANDLE" target-lang-api-name="PyLong"/>
+ <primitive-type name="Foo::SAMPLE_HANDLE" target-lang-api-name="PyLong"/>
<primitive-type name="std::size_t" target-lang-api-name="PyLong">
<conversion-rule>
@@ -74,7 +71,7 @@
</conversion-rule>
</primitive-type>
- <primitive-type name="HANDLE" target-lang-api-name="PyComplex">
+ <primitive-type name="SAMPLE_HANDLE" target-lang-api-name="PyComplex">
<include file-name="handle.h" location="local"/>
<conversion-rule>
<native-to-target>
@@ -84,6 +81,7 @@
</native-to-target>
<target-to-native>
<add-conversion type="PyNone">
+ SBK_UNUSED(%in)
%out = 0;
</add-conversion>
<add-conversion check="checkPyCapsuleOrPyCObject(%in)" type="PyObject">
@@ -168,6 +166,7 @@
%out = %OUTTYPE(str);
</add-conversion>
<add-conversion type="Py_None">
+ SBK_UNUSED(%in)
%out = %OUTTYPE();
</add-conversion>
</target-to-native>
@@ -256,6 +255,7 @@
<add-function signature="getPythonType(const char*)" return-type="PyObject">
<inject-code class="target" position="beginning">
+ SBK_UNUSED(self)
%PYARG_0 = (PyObject*) Shiboken::Conversions::getPythonTypeObject(%1);
if (!%PYARG_0)
%PYARG_0 = Py_None;
@@ -397,6 +397,7 @@
<function signature="returnNullValueTypePointer()" />
<function signature="returnNullObjectTypePointer()" />
<function signature="acceptInt(int)" />
+ <function signature="acceptIntReturnPtr(int)"/>
<function signature="acceptUInt(unsigned int)" />
<function signature="acceptLong(long)" />
<function signature="acceptULong(unsigned long)" />
@@ -418,6 +419,8 @@
<function signature="addStdStrings(const std::string&amp;, const std::string&amp;)"/>
<function signature="addStdWStrings(const std::wstring&amp;, const std::wstring&amp;)"/>
<function signature="testNullPtrT(std::nullptr_t)"/>
+ <function signature="takePolygon(Polygon&amp;&amp;)"/>
+ <function signature="takeObjectType(ObjectType&amp;&amp;)"/>
<value-type name="ArrayModifyTest">
<modify-function signature="sumIntArray(int, int*)">
@@ -426,7 +429,7 @@
</value-type>
<value-type name="ClassWithFunctionPointer">
- <suppress-warning text="skipping function 'ClassWithFunctionPointer::callFunctionPointer', unmatched parameter type 'void (*)(void*)'" />
+ <suppress-warning text="^skipping public function 'void ClassWithFunctionPointer::callFunctionPointer.*$" />
</value-type>
<value-type name="IntArray" generate="no"/>
@@ -454,6 +457,10 @@
<enum-type identified-by-value="AnonymousGlobalEnum_Value0"/>
<namespace-type name="SampleNamespace">
+ <namespace-type name="InlineNamespace">
+ <value-type name="ClassWithinInlineNamespace"/>
+ <enum-type name="EnumWithinInlineNamespace"/>
+ </namespace-type>
<enum-type name="Option"/>
<enum-type name="InValue"/>
<enum-type name="OutValue"/>
@@ -564,6 +571,14 @@
<modify-function signature="hideFunction(HideType*)" remove="all"/>
<modify-field name="toBeRenamedField" rename="renamedField"/>
<modify-field name="readOnlyField" write="false"/>
+ <modify-function signature="virtualWithOutParameter(int&amp;)const">
+ <inject-code class="shell" position="override">
+ x = virtualWithOutParameterPyOverride(gil, pyOverride.object());
+ return;
+ </inject-code>
+ </modify-function>
+ <add-function signature="virtualWithOutParameterPyOverride()"
+ return-type="int" python-override="true"/>
</object-type>
<object-type name="Derived" polymorphic-id-expression="%1->type() == Derived::TpDerived">
@@ -626,8 +641,8 @@
// CHECKTYPE and ISCONVERTIBLE are used here for test purposes, don't change them.
if (!%CHECKTYPE[ObjectTypeLayout*](layout) &amp;&amp; !%ISCONVERTIBLE[ObjectTypeLayout*](layout))
return;
- // %CHECKTYPE[ObjectTypeLayout*](layout)
- // %ISCONVERTIBLE[ObjectTypeLayout*](layout)
+ /* %CHECKTYPE[ObjectTypeLayout*](layout) */
+ /* %ISCONVERTIBLE[ObjectTypeLayout*](layout) */
ObjectTypeLayout* var;
var = %CONVERTTOCPP[ObjectTypeLayout*](layout);
// TODO-CONVERTER: erase this
@@ -714,7 +729,7 @@
</modify-function>
</object-type>
- <value-type name="ObjectTypeHolder"/>
+ <object-type name="ObjectTypeHolder"/>
<value-type name="OnlyCopy"/>
<value-type name="FriendOfOnlyCopy"/>
@@ -1385,7 +1400,7 @@
}
</template>
<modify-function signature="getMargins(int*,int*,int*,int*)const">
- <modify-argument index="0">
+ <modify-argument index="return" pyi-type="Tuple[int, int, int, int]">
<replace-type modified-type="PyObject" />
</modify-argument>
<modify-argument index="1">
@@ -1887,13 +1902,13 @@
</value-type>
<value-type name="Size">
+ <extra-includes>
+ <include file-name="string" location="global"/>
+ <include file-name="sstream" location="global"/>
+ </extra-includes>
<add-function signature="Size(const char*)">
- <inject-code class="target" position="beginning">
- %0 = new %TYPE();
- </inject-code>
- <inject-code class="target" position="end">
- Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF, const_cast&lt;char*>("setHeight"), const_cast&lt;char*>("i"), 2));
- </inject-code>
+ <inject-code class="target" position="beginning"
+ file="samplesnippets.cpp" snippet="size_char_ct"/>
</add-function>
</value-type>
<value-type name="SizeF"/>
@@ -2058,6 +2073,7 @@
<conversion-rule>
<target-to-native>
<add-conversion type="Py_None">
+ SBK_UNUSED(%in)
%out = %OUTTYPE();
</add-conversion>
<add-conversion type="PyObject" check="Shiboken::String::check(%in) || PyBytes_Check(%in)">
@@ -2209,19 +2225,20 @@
</add-function>
</value-type>
- <value-type name="SimpleFile">
+ <object-type name="SimpleFile">
<modify-function signature="open()">
<modify-argument index="return">
<remove-argument/>
</modify-argument>
<inject-code class="target" position="end" file="simplefile_glue.cpp"/>
</modify-function>
- </value-type>
+ </object-type>
<value-type name="VoidHolder" />
<object-type name="PrivateCtor" />
<object-type name="PrivateDtor" />
+ <value-type name="DeletedDefaultCtor"/>
<object-type name="Base1"/>
<object-type name="Base2"/>
@@ -2362,15 +2379,24 @@
<value-type name="Expression" />
- <object-type name="ExceptionTest" exception-handling="auto-on"/>
-
- <value-type name="ModelIndex" />
- <value-type name="ReferentModelIndex">
- <modify-function signature="operator const ModelIndex&amp;()const">
+ <object-type name="ExceptionTest" exception-handling="auto-on">
+ <modify-function signature="create(bool)">
<modify-argument index="return">
<define-ownership owner="c++"/>
</modify-argument>
+ <inject-code class="target" position="end">
+ // Test comment
+ </inject-code>
</modify-function>
+ </object-type>
+
+ <value-type name="ModelIndex" />
+ <value-type name="ReferentModelIndex">
+ <modify-function signature="operator const ModelIndex&amp;()const">
+ <modify-argument index="return">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
</value-type>
<value-type name="PersistentModelIndex" />
@@ -2383,6 +2409,31 @@
<object-type name="ObjectTypeByValue" />
+ <value-type name="StdComplex">
+ <extra-includes>
+ <include file-name="cmath" location="global"/>
+ </extra-includes>
+ <!-- PYSIDE-2446: number protocols without a Py_nb_ constant. -->
+ <add-function signature="__floor__()" return-type="double">
+ <inject-code class="target" position="end"
+ file="samplesnippets.cpp" snippet="stdcomplex_floor"/>
+ </add-function>
+ <add-function signature="__ceil__()" return-type="double">
+ <inject-code class="target" position="end"
+ file="samplesnippets.cpp" snippet="stdcomplex_ceil"/>
+ </add-function>
+ <!-- PYSIDE-2446: number protocols with Py_nb_ constants. -->
+ <add-function signature="__abs__()" return-type="double">
+ <inject-code class="target" position="end"
+ file="samplesnippets.cpp" snippet="stdcomplex_abs"/>
+ </add-function>
+ <add-function signature="__pow__(StdComplex@exp@)" return-type="StdComplex">
+ <inject-code class="target" position="end"
+ file="samplesnippets.cpp" snippet="stdcomplex_pow"/>
+ </add-function>
+
+ </value-type>
+
<object-type name="TemplatePtr">
<modify-function signature="dummy(std::list&lt;std::pair&lt;BlackBox *, BlackBox *&gt; &gt; &amp;)" rename="dummy_method" />
</object-type>
@@ -2398,20 +2449,9 @@
<suppress-warning text="horribly broken type '__off64_t'" />
<suppress-warning text="enum '__codecvt_result' does not have a type entry or is not an enum" />
- <suppress-warning text="Pure virtual method &quot;Abstract::hideFunction(HideType*)&quot; must be implement but was completely removed on typesystem." />
- <suppress-warning text="hiding of function 'takeChild' in class 'ObjectType'" />
+ <suppress-warning text="Pure virtual method 'Abstract::hideFunction(HideType*)' must be implemented but was completely removed on type system." />
<suppress-warning text="Shadowing: MDerived2::castToBase3() and MDerived3::castToBase3()" />
- <suppress-warning text="hiding of function 'takeChild' in class 'Bucket'" />
- <suppress-warning text="visibility of function 'publicMethod' modified in class 'MDerived1'" />
- <suppress-warning text="hiding of function 'doNothingInPublic3' in class 'Overload2'" />
- <suppress-warning text="hiding of function 'takeChild' in class 'ObjectModel'" />
- <suppress-warning text="hiding of function 'takeChild' in class 'ObjectView'" />
- <suppress-warning text="visibility of function 'publicMethod' modified in class 'MDerived3'" />
- <suppress-warning text="skipping function 'InjectCode::toStr', unmatched parameter type 'T const&amp;'" />
-
- <suppress-warning text="^skipping function 'std::enable_if.*ComparisonTester::operator[!=]=.*ComparisonTester.*$"/>
-
- <!-- Do not fix this warning, the generator should be able to handle this situation for Object Types. -->
- <suppress-warning text="Argument in position 1 of added function 'SampleNamespace::passReferenceToObjectType(ObjectType * arg__1)', has a type that is not a reference, while the argument in the corresponding position in C++ function 'SampleNamespace::passReferenceToObjectType(const ObjectType &amp; obj, int multiplier)' is a reference." />
+ <suppress-warning text="Visibility of function 'publicMethod' modified in class 'MDerived1'" />
+ <suppress-warning text="^skipping public function 'std::enable_if.*ComparisonTester::operator[!=]=.*ComparisonTester.*$"/>
</typesystem>
diff --git a/sources/shiboken6/tests/samplebinding/typesystypedef_test.py b/sources/shiboken6/tests/samplebinding/typesystypedef_test.py
index 5e54ef6ee..f7f5342ee 100644
--- a/sources/shiboken6/tests/samplebinding/typesystypedef_test.py
+++ b/sources/shiboken6/tests/samplebinding/typesystypedef_test.py
@@ -13,8 +13,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import (ValueWithUnitUser, ValueWithUnitDoubleInch,
- ValueWithUnitDoubleMillimeter)
+from sample import ValueWithUnitUser, ValueWithUnitDoubleInch
class TypeSysTypeDefTest(unittest.TestCase):
diff --git a/sources/shiboken6/tests/samplebinding/unsafe_parent_test.py b/sources/shiboken6/tests/samplebinding/unsafe_parent_test.py
index dbc4097da..2a7e5cac7 100644
--- a/sources/shiboken6/tests/samplebinding/unsafe_parent_test.py
+++ b/sources/shiboken6/tests/samplebinding/unsafe_parent_test.py
@@ -15,6 +15,7 @@ init_paths()
from sample import ObjectType
+
class DerivedObjectType(ObjectType):
def isPython(self):
return True
@@ -22,12 +23,13 @@ class DerivedObjectType(ObjectType):
def createChild(self, parent):
return DerivedObjectType(parent)
+
class ParentTest(unittest.TestCase):
def testUunsafeParent(self):
o = DerivedObjectType()
o.callVirtualCreateChild()
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/useraddedctor_test.py b/sources/shiboken6/tests/samplebinding/useraddedctor_test.py
index 3aee8d6f7..45d4095b6 100644
--- a/sources/shiboken6/tests/samplebinding/useraddedctor_test.py
+++ b/sources/shiboken6/tests/samplebinding/useraddedctor_test.py
@@ -12,14 +12,15 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Size
+
class PointTest(unittest.TestCase):
def testUsingSelfOnCtor(self):
# This is a user added ctor and no errors should happen!
- s = Size("oi")
+ s = Size("3x2")
self.assertEqual(s.height(), 2)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/virtualdtor_test.py b/sources/shiboken6/tests/samplebinding/virtualdtor_test.py
index 69c3479c5..6be870269 100644
--- a/sources/shiboken6/tests/samplebinding/virtualdtor_test.py
+++ b/sources/shiboken6/tests/samplebinding/virtualdtor_test.py
@@ -16,10 +16,12 @@ init_paths()
from sample import VirtualDtor
+
class ExtendedVirtualDtor(VirtualDtor):
def __init__(self):
VirtualDtor.__init__(self)
+
class VirtualDtorTest(unittest.TestCase):
'''Test case for virtual destructor.'''
@@ -59,4 +61,3 @@ class VirtualDtorTest(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/virtualmethods_test.py b/sources/shiboken6/tests/samplebinding/virtualmethods_test.py
index 7be424e26..52dc66c90 100644
--- a/sources/shiboken6/tests/samplebinding/virtualmethods_test.py
+++ b/sources/shiboken6/tests/samplebinding/virtualmethods_test.py
@@ -14,10 +14,11 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Point, Str, StrList, VirtualDaughter, VirtualMethods
import warnings
+
class ExtendedVirtualMethods(VirtualMethods):
def __init__(self):
VirtualMethods.__init__(self)
@@ -36,6 +37,7 @@ class ExtendedVirtualMethods(VirtualMethods):
# check if recursion is caused by injected code that calls C++.
return VirtualMethods.recursionOnModifiedVirtual(self, arg) + 10
+
class ExtendedVirtualDaughter(VirtualDaughter):
def __init__(self, name):
VirtualDaughter.__init__(self, name)
@@ -45,6 +47,7 @@ class ExtendedVirtualDaughter(VirtualDaughter):
self.grand_daughter_name_called = True
return VirtualDaughter.name(self).prepend('Extended')
+
class ExtendedExtendedVirtualDaughter(ExtendedVirtualDaughter):
def __init__(self, name):
ExtendedVirtualDaughter.__init__(self, name)
@@ -54,6 +57,7 @@ class ExtendedExtendedVirtualDaughter(ExtendedVirtualDaughter):
self.grand_grand_daughter_name_called = True
return ExtendedVirtualDaughter.name(self).prepend('Extended')
+
class VirtualMethodsTest(unittest.TestCase):
'''Test case for virtual methods'''
@@ -66,7 +70,8 @@ class VirtualMethodsTest(unittest.TestCase):
gc.collect()
def testReimplementedVirtualMethod0(self):
- '''Test Python override of a virtual method with various different parameters is correctly called from C++.'''
+ '''Test Python override of a virtual method with various different parameters
+ is correctly called from C++.'''
vm = VirtualMethods()
evm = ExtendedVirtualMethods()
pt = Point(1.1, 2.2)
@@ -120,6 +125,6 @@ class PrettyErrorMessageTest(unittest.TestCase):
obj = ExtendedVirtualMethods()
self.assertRaises(RuntimeWarning, obj.callStrListToStdList, StrList())
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/visibilitychange_test.py b/sources/shiboken6/tests/samplebinding/visibilitychange_test.py
index 1b810e839..becdf7423 100644
--- a/sources/shiboken6/tests/samplebinding/visibilitychange_test.py
+++ b/sources/shiboken6/tests/samplebinding/visibilitychange_test.py
@@ -11,17 +11,17 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from sample import *
+from sample import Base1, MDerived1
+
class VisibilityChangeTest(unittest.TestCase):
def testVisibilityChange(self):
b1 = Base1()
- b1.publicMethod() # ok...
+ b1.publicMethod() # ok...
d1 = MDerived1()
- self.assertRaises(TypeError, d1.publicMethod);
+ self.assertRaises(TypeError, d1.publicMethod)
+
if __name__ == '__main__':
unittest.main()
-
-
diff --git a/sources/shiboken6/tests/samplebinding/voidholder_test.py b/sources/shiboken6/tests/samplebinding/voidholder_test.py
index 63882cc8a..186cb473e 100644
--- a/sources/shiboken6/tests/samplebinding/voidholder_test.py
+++ b/sources/shiboken6/tests/samplebinding/voidholder_test.py
@@ -16,6 +16,7 @@ init_paths()
from sample import VoidHolder, Point
from shiboken6 import Shiboken
+
class VoidHolderTest(unittest.TestCase):
'''Test case for void pointer manipulation.'''
@@ -44,6 +45,6 @@ class VoidHolderTest(unittest.TestCase):
voidholder = VoidHolder()
self.assertEqual(voidholder.voidPointer(), None)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/sources/shiboken6/tests/samplebinding/weakref_test.py b/sources/shiboken6/tests/samplebinding/weakref_test.py
index 317dfb53c..01c6d58d5 100644
--- a/sources/shiboken6/tests/samplebinding/weakref_test.py
+++ b/sources/shiboken6/tests/samplebinding/weakref_test.py
@@ -30,7 +30,7 @@ class WeakrefBasicTest(unittest.TestCase):
def testBasic(self):
'''ObjectType weakref'''
obj = ObjectType()
- ref = weakref.ref(obj, self.cb)
+ ref = weakref.ref(obj, self.cb) # noqa: F841
del obj
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
@@ -39,7 +39,7 @@ class WeakrefBasicTest(unittest.TestCase):
def testPrivateDtor(self):
'''PrivateDtor weakref'''
obj = PrivateDtor.instance()
- ref = weakref.ref(obj, self.cb)
+ ref = weakref.ref(obj, self.cb) # noqa: F841
del obj
# PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
gc.collect()
diff --git a/sources/shiboken6/tests/samplebinding/writableclassdict_test.py b/sources/shiboken6/tests/samplebinding/writableclassdict_test.py
index e3ba10082..dfc962db9 100644
--- a/sources/shiboken6/tests/samplebinding/writableclassdict_test.py
+++ b/sources/shiboken6/tests/samplebinding/writableclassdict_test.py
@@ -13,7 +13,10 @@ init_paths()
from sample import Point
-class ExtPoint(Point): pass
+
+class ExtPoint(Point):
+ pass
+
class TestWritableClassDict(unittest.TestCase):
def testSetattrOnClass(self):
@@ -29,5 +32,6 @@ class TestWritableClassDict(unittest.TestCase):
pt = ExtPoint()
self.assertEqual(pt.bar, 321)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/shibokenmodule/module_test.py b/sources/shiboken6/tests/shibokenmodule/module_test.py
index 9b9a5ad90..9f9f8f5a4 100644
--- a/sources/shiboken6/tests/shibokenmodule/module_test.py
+++ b/sources/shiboken6/tests/shibokenmodule/module_test.py
@@ -7,17 +7,19 @@ import unittest
from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
-from shiboken_paths import init_paths
+from shiboken_paths import init_paths # noqa: E402
init_paths()
-from shiboken6 import Shiboken
-from sample import *
+from shiboken6 import Shiboken # noqa: E402
+from sample import BlackBox, ObjectType, ObjectModel, ObjectView, Point # noqa: E402
+
class MultipleInherited (ObjectType, Point):
def __init__(self):
ObjectType.__init__(self)
Point.__init__(self)
+
class TestShiboken(unittest.TestCase):
def testIsValid(self):
self.assertTrue(Shiboken.isValid(object()))
@@ -43,6 +45,16 @@ class TestShiboken(unittest.TestCase):
self.assertTrue(Shiboken.createdByPython(bb))
bb.disposeObjectType(bb.keepObjectType(obj))
+ def testWrapInstancePreserveId(self):
+ """PYSIDE-31: Verify that wrapInstance() returns the existing wrapper
+ even if a base class type is specified."""
+ v = ObjectView() # inherits ObjectType
+ addresses = Shiboken.getCppPointer(v)
+ self.assertTrue(addresses)
+ address = addresses[0]
+ wrapped = Shiboken.wrapInstance(address, ObjectType)
+ self.assertEqual(id(wrapped), id(v))
+
def testIsOwnedByPython(self):
obj = ObjectType()
self.assertTrue(Shiboken.ownedByPython(obj))
@@ -55,7 +67,7 @@ class TestShiboken(unittest.TestCase):
p = ObjectType()
obj = ObjectType(p)
obj2 = ObjectType(obj)
- obj3 = ObjectType(obj)
+ obj3 = ObjectType(obj) # noqa: F841
self.assertEqual(Shiboken.dump(None), "Ordinary Python type.")
Shiboken.dump(obj)
@@ -69,9 +81,9 @@ class TestShiboken(unittest.TestCase):
# Don't crash even after deleting an object
Shiboken.invalidate(obj)
- Shiboken.dump(obj) # deleted
- Shiboken.dump(p) # child deleted
- Shiboken.dump(obj2) # parent deleted
+ Shiboken.dump(obj) # deleted
+ Shiboken.dump(p) # child deleted
+ Shiboken.dump(obj2) # parent deleted
def testDelete(self):
obj = ObjectType()
diff --git a/sources/shiboken6/tests/smartbinding/CMakeLists.txt b/sources/shiboken6/tests/smartbinding/CMakeLists.txt
index b4b86d733..2e729321e 100644
--- a/sources/shiboken6/tests/smartbinding/CMakeLists.txt
+++ b/sources/shiboken6/tests/smartbinding/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
project(smart)
set(smart_TYPESYSTEM
@@ -21,22 +24,30 @@ ${CMAKE_CURRENT_BINARY_DIR}/smart/std_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/std_optional_int_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/std_optional_integer_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/std_unique_ptr_integer_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/smart/std_unique_ptr_integer2_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/std_unique_ptr_int_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/stdoptionaltestbench_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/stduniqueptrtestbench_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/smart/stduniqueptrvirtualmethodtester_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/smart/test_wrapper.cpp
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/smart-binding.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt" @ONLY)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
add_custom_command(
-OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
-BYPRODUCTS ${smart_SRC}
-COMMAND Shiboken6::shiboken6 --project-file=${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt ${GENERATOR_EXTRA_FLAGS}
-DEPENDS ${smart_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
-WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-COMMENT "Running generator for 'smart' test binding..."
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log"
+ BYPRODUCTS ${smart_SRC}
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --project-file=${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt
+ ${GENERATOR_EXTRA_FLAGS}
+ DEPENDS ${smart_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h Shiboken6::shiboken6
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Running generator for 'smart' test binding..."
)
add_library(smart MODULE ${smart_SRC})
diff --git a/sources/shiboken6/tests/smartbinding/smart-binding.txt.in b/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
index 699f0bfe6..a2c73c6bf 100644
--- a/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
+++ b/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers
diff --git a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py
index 74dc89bc4..8d4272558 100644
--- a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py
+++ b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py
@@ -231,6 +231,9 @@ class SmartPointerTests(unittest.TestCase):
# Create a shared pointer to an Integer2
integer2 = o.createSharedPtrInteger2()
+ # User defined name
+ self.assertEqual(type(integer2).__name__, "SmartInteger2Ptr")
+ self.assertTrue("smart.Test.SmartInteger2Ptr" in repr(type(integer2)))
self.assertEqual(integer2.value(), 456)
# pass Smart<Integer2> to a function that accepts Smart<Integer>
@@ -259,7 +262,7 @@ class SmartPointerTests(unittest.TestCase):
self.assertTrue(five > four)
self.assertRaises(NotImplementedError,
- lambda : Obj.createNullSharedPtrInteger() == four)
+ lambda: Obj.createNullSharedPtrInteger() == four)
def testSmartPointerObjectComparison(self):
"""Test a pointee class without comparison operators."""
diff --git a/sources/shiboken6/tests/smartbinding/smartbinding.pyproject b/sources/shiboken6/tests/smartbinding/smartbinding.pyproject
new file mode 100644
index 000000000..d0855ef82
--- /dev/null
+++ b/sources/shiboken6/tests/smartbinding/smartbinding.pyproject
@@ -0,0 +1,7 @@
+{
+ "files": ["smart_pointer_test.py",
+ "std_optional_test.py",
+ "std_shared_ptr_test.py",
+ "std_unique_ptr_test.py",
+ "typesystem_smart.xml"]
+}
diff --git a/sources/shiboken6/tests/smartbinding/std_optional_test.py b/sources/shiboken6/tests/smartbinding/std_optional_test.py
index be969d0f5..bee573548 100644
--- a/sources/shiboken6/tests/smartbinding/std_optional_test.py
+++ b/sources/shiboken6/tests/smartbinding/std_optional_test.py
@@ -2,7 +2,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import gc
import os
import sys
import unittest
diff --git a/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py b/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
index b4b9808c6..2e6aea3d9 100644
--- a/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
+++ b/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
@@ -2,7 +2,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import gc
import os
import sys
import unittest
@@ -28,6 +27,8 @@ class VirtualTester(StdSharedPtrVirtualMethodTester):
class StdSharedPtrTests(unittest.TestCase):
def testInteger(self):
p = StdSharedPtrTestBench.createInteger()
+ # PYSIDE-2462: Ensure Integer's __dir__ entries in the pointer's
+ self.assertTrue("printInteger" in dir(p))
StdSharedPtrTestBench.printInteger(p)
self.assertTrue(p)
call_func_on_ptr(p)
diff --git a/sources/shiboken6/tests/smartbinding/std_unique_ptr_test.py b/sources/shiboken6/tests/smartbinding/std_unique_ptr_test.py
index f21466302..9c7ef2f01 100644
--- a/sources/shiboken6/tests/smartbinding/std_unique_ptr_test.py
+++ b/sources/shiboken6/tests/smartbinding/std_unique_ptr_test.py
@@ -2,7 +2,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import gc
import os
import sys
import unittest
@@ -11,7 +10,7 @@ from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from shiboken_paths import init_paths
init_paths()
-from smart import Integer, StdUniquePtrTestBench, StdUniquePtrVirtualMethodTester, std
+from smart import Integer, Integer2, StdUniquePtrTestBench, StdUniquePtrVirtualMethodTester, std
def call_func_on_ptr(ptr):
@@ -54,6 +53,17 @@ class StdUniquePtrTests(unittest.TestCase):
np = std.unique_ptr_Integer(iv)
self.assertEqual(np.value(), 42)
+ def test_derived(self):
+ iv2 = Integer2() # Construct from pointee
+ iv2.setValue(42)
+ p = std.unique_ptr_Smart_Integer2(iv2)
+ self.assertEqual(p.value(), 42)
+ StdUniquePtrTestBench.printInteger2(p) # unique_ptr by ref
+ self.assertTrue(p)
+ StdUniquePtrTestBench.printInteger(p) # conversion
+ # FIXME: This fails, pointer is moved in value conversion
+ # self.assertTrue(p)
+
def testInt(self):
p = StdUniquePtrTestBench.createInt() # unique_ptr by ref
StdUniquePtrTestBench.printInt(p)
diff --git a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
index 748e5a0d3..261d5f15d 100644
--- a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
+++ b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
@@ -28,7 +28,7 @@
-->
<smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount"
null-check-method="isNull"
- instantiations="Integer,Smart::Integer2,Obj"/>
+ instantiations="Integer,Smart::Integer2=Test::SmartInteger2Ptr,Obj"/>
<object-type name="Obj" />
<value-type name="Integer" />
@@ -57,7 +57,7 @@
<smart-pointer-type name="unique_ptr" type="unique" getter="get"
value-check-method="operator bool"
reset-method="reset"
- instantiations="Integer,int">
+ instantiations="Integer,Smart::Integer2,int">
<include file-name="memory" location="global"/>
</smart-pointer-type>
@@ -74,4 +74,8 @@
<object-type name="StdUniquePtrTestBench"/>
<object-type name="StdUniquePtrVirtualMethodTester"/>
+ <namespace-type name="Test">
+ <enum-type name="DummyEnum"/>
+ </namespace-type>
+
</typesystem>
diff --git a/sources/shiboken6/tests/test_generator/CMakeLists.txt b/sources/shiboken6/tests/test_generator/CMakeLists.txt
index b48ae37da..e1d078894 100644
--- a/sources/shiboken6/tests/test_generator/CMakeLists.txt
+++ b/sources/shiboken6/tests/test_generator/CMakeLists.txt
@@ -1,4 +1,7 @@
-cmake_minimum_required(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
project(test_generator)
set(dummy_generator_SRC dummygenerator.cpp)
diff --git a/sources/shiboken6/tests/test_generator/run_test.cmake b/sources/shiboken6/tests/test_generator/run_test.cmake
index 34a821d80..37e40b993 100644
--- a/sources/shiboken6/tests/test_generator/run_test.cmake
+++ b/sources/shiboken6/tests/test_generator/run_test.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# The tests are run through this script due to a limitation
# on versions of CMake lesser than 2.8, that prevent setting
# environment variables for tests from working.